├── .mvn_exec_yarn ├── .yarnrc.yml ├── .github ├── CODEOWNERS ├── release-drafter.yml ├── dependabot.yml └── workflows │ ├── release-drafter.yml │ └── jenkins-security-scan.yml ├── .mvn ├── maven.config └── extensions.xml ├── NOTICE.txt ├── docs └── images │ ├── 001.jpg │ ├── 002.gif │ ├── 003.jpg │ ├── 004.gif │ ├── 005.gif │ ├── 006.gif │ ├── 007.png │ ├── 008.gif │ ├── 009.gif │ ├── 010.gif │ ├── 011.gif │ ├── 012.gif │ ├── 013.png │ ├── 014.png │ ├── 015.png │ ├── 016.gif │ ├── 017.jpg │ ├── 018.png │ └── 019.png ├── src ├── main │ ├── webapp │ │ ├── help-filterLengthParameters.html │ │ ├── help-hidden.html │ │ ├── help │ │ │ └── parameter │ │ │ │ ├── active-choices-choice.html │ │ │ │ ├── active-choices-cascade-choice.html │ │ │ │ └── active-choices-dynamic-reference-parameter.html │ │ ├── help-filterableParameters.html │ │ ├── help-omitValueField.html │ │ ├── help-referencedParameters.html │ │ ├── css │ │ │ └── unochoice.css │ │ └── help-dynamicReferenceScript.html │ ├── resources │ │ ├── index.jelly │ │ └── org │ │ │ └── biouno │ │ │ └── unochoice │ │ │ ├── DynamicReferenceParameter │ │ │ ├── orderedList.jelly │ │ │ ├── inputElement.jelly │ │ │ ├── formattedHtml.jelly │ │ │ ├── unorderedList.jelly │ │ │ ├── dynamic-reference-parameter.js │ │ │ ├── index.jelly │ │ │ └── config.jelly │ │ │ ├── common │ │ │ ├── multi-select.js │ │ │ ├── checkbox-content.js │ │ │ ├── radio-content.js │ │ │ ├── choiceParameterCommon.jelly │ │ │ ├── selectContent.jelly │ │ │ ├── checkboxContent.jelly │ │ │ └── radioContent.jelly │ │ │ ├── ChoiceParameter │ │ │ ├── render-choice-parameter.js │ │ │ ├── index.jelly │ │ │ └── config.jelly │ │ │ ├── model │ │ │ ├── GroovyScript │ │ │ │ ├── config.jelly │ │ │ │ └── help.html │ │ │ └── ScriptlerScript │ │ │ │ └── config.jelly │ │ │ ├── stapler │ │ │ └── unochoice.jelly │ │ │ └── CascadeChoiceParameter │ │ │ ├── index.jelly │ │ │ ├── cascade-choice-parameter.js │ │ │ └── config.jelly │ └── java │ │ └── org │ │ └── biouno │ │ └── unochoice │ │ ├── model │ │ ├── ScriptDescriptor.java │ │ ├── AbstractScript.java │ │ └── Script.java │ │ ├── UnoChoiceParameter.java │ │ ├── ScriptableParameter.java │ │ ├── UnoChoiceParameterDescriptor.java │ │ ├── CascadableParameter.java │ │ ├── util │ │ ├── SafeHtmlExtendedMarkupFormatter.java │ │ └── ScriptCallback.java │ │ └── ChoiceParameter.java └── test │ ├── resources │ └── org │ │ └── biouno │ │ └── unochoice │ │ ├── issue63983 │ │ └── TestSandboxAndApproval │ │ │ ├── README.md │ │ │ ├── users │ │ │ ├── admin │ │ │ │ └── config.xml │ │ │ └── summerworkers │ │ │ │ └── config.xml │ │ │ └── config.xml │ │ ├── PipelineWithScriptlerParameters.groovy │ │ ├── issue72105 │ │ └── TestJobDslWithScriptlerScriptWithParameters │ │ │ └── test │ │ │ └── jobs │ │ │ └── job │ │ │ └── config.xml │ │ └── issue74963 │ │ └── TestSelectWithSpinningWheelMayBeNull │ │ └── test │ │ └── jobs │ │ └── test │ │ └── config.xml │ ├── js │ ├── runner.sh │ ├── runner.bat │ └── lib │ │ ├── tests.html │ │ ├── runner-list.js │ │ ├── runner.js │ │ └── qunit-1.14.0.css │ └── java │ └── org │ ├── jenkinsci │ └── plugins │ │ └── scriptler │ │ ├── package-info.java │ │ └── ScriptlerHelper.java │ └── biouno │ └── unochoice │ ├── issue69448 │ ├── package-info.java │ └── TestDefaultValuesWithScriptReturningMap.java │ ├── issue71909 │ └── package-info.java │ ├── issue72105 │ └── package-info.java │ ├── issue73239 │ ├── package-info.java │ └── TestCascadeParameterIsEmpty.java │ ├── issue74963 │ └── package-info.java │ ├── issue74967 │ ├── package-info.java │ └── TestFilter.java │ ├── issue34818 │ ├── package-info.java │ └── TestGlobalNodePropertiesScript.java │ ├── issue38532 │ ├── package-info.java │ └── TestParameterValuesWithEquals.java │ ├── issue48448 │ ├── package-info.java │ └── TestParameterObjectIsPresent.java │ ├── issue49260 │ ├── package-info.java │ └── TestProjectDifferenceAcrossFolders.java │ ├── issue62215 │ ├── package-info.java │ └── TestMarkupFormatterAllowsRequiredElementsInScriptOutput.java │ ├── issue51296 │ ├── package-info.java │ └── TestProjectNameAfterRenaming.java │ ├── issue63983 │ └── package-info.java │ ├── issue61068 │ └── package-info.java │ ├── issue65235 │ └── package-info.java │ ├── issue62835 │ └── package-info.java │ ├── util │ ├── TestScriptCallback.java │ └── PrintAllWebConsolerLogger.java │ ├── TestParametersOrder.java │ ├── TestAbstractUnoChoiceParameter.java │ ├── Security470Test.java │ ├── TestChoiceParameter.java │ ├── TestDynamicReferenceParameter.java │ ├── jenkins_cert_1954 │ └── TestParametersXssVulnerabilities.java │ └── jenkins_cert_2192 │ └── TestDynamicReferenceXss.java ├── .gitignore ├── Jenkinsfile ├── tsconfig.json ├── .editorconfig ├── webpack.config.js ├── LICENSE.txt └── package.json /.mvn_exec_yarn: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkinsci/active-choices-plugin-developers 2 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | The original design was inspired in Dynamic Parameters Plug-in (Apache License). -------------------------------------------------------------------------------- /docs/images/001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/001.jpg -------------------------------------------------------------------------------- /docs/images/002.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/002.gif -------------------------------------------------------------------------------- /docs/images/003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/003.jpg -------------------------------------------------------------------------------- /docs/images/004.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/004.gif -------------------------------------------------------------------------------- /docs/images/005.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/005.gif -------------------------------------------------------------------------------- /docs/images/006.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/006.gif -------------------------------------------------------------------------------- /docs/images/007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/007.png -------------------------------------------------------------------------------- /docs/images/008.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/008.gif -------------------------------------------------------------------------------- /docs/images/009.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/009.gif -------------------------------------------------------------------------------- /docs/images/010.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/010.gif -------------------------------------------------------------------------------- /docs/images/011.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/011.gif -------------------------------------------------------------------------------- /docs/images/012.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/012.gif -------------------------------------------------------------------------------- /docs/images/013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/013.png -------------------------------------------------------------------------------- /docs/images/014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/014.png -------------------------------------------------------------------------------- /docs/images/015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/015.png -------------------------------------------------------------------------------- /docs/images/016.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/016.gif -------------------------------------------------------------------------------- /docs/images/017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/017.jpg -------------------------------------------------------------------------------- /docs/images/018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/018.png -------------------------------------------------------------------------------- /docs/images/019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/active-choices-plugin/master/docs/images/019.png -------------------------------------------------------------------------------- /src/main/webapp/help-filterLengthParameters.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | How many characters a user must enter before the filter is applied. 4 |

5 |
-------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | work/ 2 | .idea/ 3 | target/ 4 | test-output/ 5 | .classpath 6 | .settings/ 7 | .project 8 | **/*~ 9 | *.iml 10 | node/ 11 | node_modules/ 12 | src/main/webapp/js 13 | -------------------------------------------------------------------------------- /src/main/webapp/help-hidden.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | If enabled the parameter is not displayed in the UI, but will be present in the form 4 | and will be sent to the server. 5 |

6 |
7 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | buildPlugin( 2 | useContainerAgent: true, 3 | failFast: false, 4 | forkCount: '1C', 5 | configurations: [ 6 | [platform: 'linux', jdk: 21], 7 | // [platform: 'windows', jdk: 17], 8 | ] 9 | ) 10 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc 2 | --- 3 | _extends: .github 4 | name-template: $NEXT_PATCH_VERSION 5 | tag-template: uno-choice-$NEXT_PATCH_VERSION 6 | version-template: $MAJOR.$MINOR.$PATCH 7 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | This plug-in provides additional parameter types for jobs, that allow you to cascade 4 | changes and render images or other HTML elements instead of the traditional parameter. 5 |
6 | -------------------------------------------------------------------------------- /src/main/webapp/help/parameter/active-choices-choice.html: -------------------------------------------------------------------------------- 1 |
2 |

This is a simple parameter that executes a script and 3 | renders the returned values as an HTML element. This 4 | element can be a list, a dropdown box, radio or check 5 | boxes.

6 |
7 | -------------------------------------------------------------------------------- /src/test/resources/org/biouno/unochoice/issue63983/TestSandboxAndApproval/README.md: -------------------------------------------------------------------------------- 1 | Copied from https://github.com/jenkinsci/multi-slave-config-plugin/tree/cfa6f78fe7fc2f10c75b825db5a3616c198bc776/src/test/resources/com/sonyericsson/hudson/plugins/multislaveconfigplugin/NodeManageLinkHudsonTest -------------------------------------------------------------------------------- /src/main/webapp/help-filterableParameters.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | If enabled a text box will appear next to this element and will permit the user to filter its entries. 4 | The list values never get re-evaluated. In other words, the lookup happens in a cached version of the 5 | options. 6 |

7 |
8 | -------------------------------------------------------------------------------- /src/main/webapp/help-omitValueField.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | By default Dynamic Reference Parameters always include a hidden input for the value. 4 | If your script creates an input HTML element, you can check this option and the 5 | value input field will be omitted. 6 |

7 |
8 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/DynamicReferenceParameter/orderedList.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |
  1. ${entry}
  2. 6 |
    7 |
8 |
-------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/DynamicReferenceParameter/inputElement.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/webapp/help-referencedParameters.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Comma separated list of other job parameters referenced in the uno-choice script. 4 | When any of the referenced parameters are updated, the Groovy script will re-evaluate 5 | the choice list using the updated values of referenced parameters. 6 |

7 |
8 | -------------------------------------------------------------------------------- /src/main/webapp/help/parameter/active-choices-cascade-choice.html: -------------------------------------------------------------------------------- 1 |
2 |

Accepts another parameter as reference, and updates itself 3 | whenever the other parameter is changed. The value of the 4 | other parameter is made available as a variable that can 5 | be used in this parameter's script.

6 |
7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src/**/*.ts" 4 | ], 5 | "exclude": [ 6 | "src/**/*.test.ts" 7 | ], 8 | "compilerOptions": { 9 | "module": "CommonJS", 10 | "target": "es5", 11 | "noImplicitAny": true, 12 | "sourceMap": true, 13 | "outDir": "dist" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/common/multi-select.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("DOMContentLoaded", () => { 2 | document.querySelectorAll(".multi-select-data-holder").forEach((dataHolder) => { 3 | const { visibleItemCount, multiSelectId } = dataHolder.dataset; 4 | document.getElementById(multiSelectId).size = visibleItemCount; 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/ChoiceParameter/render-choice-parameter.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("DOMContentLoaded", () => { 2 | document.querySelectorAll(".choice-parameter-data-holder").forEach((dataHolder) => { 3 | const { paramName, filterLength } = dataHolder.dataset; 4 | UnoChoice.renderChoiceParameter(paramName, filterLength); 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/model/GroovyScript/config.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | Script 4 | 5 | 6 | Fallback Script 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/js/runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This bash-shell script is a wrapper for phantomjs 4 | # It first checks if the program exists and is executable, if so 5 | # runs phantomjs normally. Otherwise just pretend nothing happened 6 | # and keeps with the rest of the project build. 7 | 8 | PHANTOMJS_EXEC=$(which phantomjs) 9 | 10 | if [[ -x $PHANTOMJS_EXEC ]]; 11 | then 12 | phantomjs "$1" "$2" 13 | else 14 | exit 0 15 | fi 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 160 10 | tab_width = 4 11 | ij_continuation_indent_size = 8 12 | ij_formatter_off_tag = @formatter:off 13 | ij_formatter_on_tag = @formatter:on 14 | ij_formatter_tags_enabled = true 15 | ij_smart_tabs = false 16 | ij_visual_guides = none 17 | ij_wrap_on_typing = false 18 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.jenkins.tools.incrementals 4 | git-changelist-maven-extension 5 | 1.13 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/test/js/runner.bat: -------------------------------------------------------------------------------- 1 | REM This batch script is a wrapper for phantomjs 2 | REM It first checks if the program exists and is executable, if so 3 | REM runs phantomjs normally. Otherwise just pretend nothing happened 4 | REM and keeps with the rest of the project build. 5 | 6 | where phantomjs > tmp.txt 7 | SET /p PHANTOMJS_EXEC= 2 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/help/parameter/active-choices-dynamic-reference-parameter.html: -------------------------------------------------------------------------------- 1 |
2 |

This parameter is a special cascade choice parameter. It was 3 | designed based on the cascade choice parameter, so it is also 4 | able to re-render itself whenever another parameter changes.

5 | 6 |

The difference of this parameter is that users have more 7 | freedom on how the HTML element is rendered (if rendered at 8 | all). This is useful in cases where users want to display a 9 | custom HTML element, write JavaScript that renders something 10 | like D3.js or another JavaScript library.

11 |
12 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/DynamicReferenceParameter/unorderedList.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 |
  • ${entry}
  • 11 |
    12 |
13 |
-------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = (env, argv) => ({ 4 | mode: "development", 5 | entry: { 6 | "UnoChoice": [ 7 | path.join(__dirname, "src/main/js/UnoChoice.es6"), 8 | ], 9 | "Util": [ 10 | path.join(__dirname, "src/main/js/Util.ts"), 11 | ], 12 | }, 13 | output: { 14 | path: path.join(__dirname, "src/main/webapp/js"), 15 | iife: false, 16 | }, 17 | devtool: argv.mode === "production" ? "source-map" : "eval-source-map", 18 | module: { 19 | rules: [ 20 | {use: "ts-loader", test: /\.ts$/}, 21 | {use: "babel-loader", test: /\.es6$/}, 22 | ], 23 | }, 24 | externals: { 25 | jquery: 'jQuery' 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /.github/workflows/jenkins-security-scan.yml: -------------------------------------------------------------------------------- 1 | # Jenkins Security Scan 2 | # For more information, see: https://www.jenkins.io/doc/developer/security/scan/ 3 | --- 4 | name: Jenkins Security Scan 5 | 6 | on: 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | types: [opened, synchronize, reopened] 12 | workflow_dispatch: 13 | 14 | permissions: 15 | security-events: write 16 | contents: read 17 | actions: read 18 | 19 | jobs: 20 | security-scan: 21 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 22 | with: 23 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. 24 | # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default. 25 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/common/radio-content.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("DOMContentLoaded", () => { 2 | document.querySelectorAll(".radio-content-data-holder").forEach((dataHolder) => { 3 | const { itemCount, maxCount, randomName } = dataHolder.dataset; 4 | 5 | if (itemCount > maxCount) { 6 | document.getElementById(`ecp_${randomName}`).style.height = "255px"; 7 | document.getElementById(`ecp_${randomName}`).style.overflowY = "auto"; 8 | } 9 | }); 10 | 11 | document.querySelectorAll(".radio-content-radio-input").forEach((radioInput) => { 12 | radioInput.addEventListener("change", (event) => { 13 | const target = event.target; 14 | const name = target.getAttribute("name"); 15 | const id = target.getAttribute("otherid"); 16 | 17 | UnoChoice.fakeSelectRadioButton(name, id); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/CascadeChoiceParameter/index.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | ${it.parameters.clear()} 4 | 5 | 6 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/model/GroovyScript/help.html: -------------------------------------------------------------------------------- 1 |
2 |

Use a Groovy script to define the parameter.

3 |

The Script will be evaluated first, and if it fails (e.g. throws an exception), 4 | the Fallback Script will be used as a fallback.

5 |

This script integrates with Script Security plugin 6 | to allow regular Jenkins users to configure this parameter, while limiting what they can do for security.

7 |
8 |

If this script is used for any of the HTML choice types of an Active Choices Reactive Reference Parameter, 9 | the resulting HTML output will be sanitized to remove everything but basic formatting, like script tags, unless the script runs outside the sandbox. 10 | This mode requires approval from a Jenkins administrator to prevent cross-site scripting (HTML) and arbitrary code execution (Groovy).

11 |
-------------------------------------------------------------------------------- /src/main/webapp/css/unochoice.css: -------------------------------------------------------------------------------- 1 | .js-loading-overlay { 2 | position:absolute; 3 | top:0; bottom:0; 4 | left:0; right:0; 5 | 6 | z-index:199; 7 | 8 | background:#fff; 9 | opacity:0.5; 10 | 11 | border-radius: inherit; 12 | } 13 | 14 | .active-choice { 15 | display: flex; 16 | flex-direction: column; 17 | align-items: flex-start; 18 | } 19 | 20 | .uno_choice_filter { 21 | width: 200px; 22 | } 23 | 24 | .ac-spinner { 25 | display: none; 26 | position: absolute; 27 | margin-left: -22px; 28 | margin-top: 10px; 29 | } 30 | 31 | .ac-container__wrapper { 32 | padding-right: 25px 33 | } 34 | 35 | .ac-container { 36 | display: flex; 37 | flex-direction: column; 38 | gap: 5px; 39 | } 40 | 41 | .ac-select { 42 | overflow-y: auto; 43 | border: 0; 44 | width: 100%; 45 | } 46 | 47 | .ac-select:focus-visible { 48 | outline: 0; 49 | } 50 | 51 | .ac-select__input { 52 | padding: 0; 53 | overflow: hidden; 54 | transition: none; 55 | } 56 | 57 | .ac-select__input:has(>select:focus) { 58 | border-color: var(--focus-input-border); 59 | box-shadow: var(--form-input-glow--focus); 60 | outline: none; 61 | } 62 | -------------------------------------------------------------------------------- /src/test/resources/org/biouno/unochoice/issue63983/TestSandboxAndApproval/users/admin/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Administrator 4 | 5 | 6 | All 7 | 8 | 9 | 10 | All 11 | false 12 | false 13 | 14 | 15 | 16 | 17 | EsFUDz:08c2dac88b514c565c5179d8f29a62fafef3477b138fa79ca7ca7d0031a93650 18 | 19 | 20 | admin@localhost 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2020 Ioannis K. Moutsatsos, Bruno P. Kinoshita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/test/resources/org/biouno/unochoice/issue63983/TestSandboxAndApproval/users/summerworkers/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Summerworkers 4 | 5 | 6 | All 7 | 8 | 9 | 10 | All 11 | false 12 | false 13 | 14 | 15 | 16 | 17 | qmNQcK:20e30ce85a3820d63de52a0e38db6393b7c35a14a8c3b2d286f85b2eee047353 18 | 19 | 20 | summerworkers@localhost 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/webapp/help-dynamicReferenceScript.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | This script is evaluated and used to render different HTML elements. The 4 | following elements are present as parameters for the Groovy script. 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
EntryValue
jenkinsProjectJenkins job project
jenkinsBuildJenkins build
/home/kinow/jenkins-workspace/test1/work/jobs/1/workspace/archivedArtifact1.txt
...
27 |

28 | When using an image gallery, you must return a list of images. Use the 29 | include pattern to filter the archived artifacts and, if necessary, 30 | execute extra code in your Groovy script to select which files should 31 | be rendered. Below the simplest way to create a gallery with archived 32 | images. 33 |

34 |
35 |     return new ArrayList(binding.variables.artifacts.keySet())
36 |     
37 | 38 |
-------------------------------------------------------------------------------- /src/test/java/org/jenkinsci/plugins/scriptler/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * For testing scriptler-plugin. 27 | */ 28 | package org.jenkinsci.plugins.scriptler; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue69448/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-69448. 27 | * 28 | * @since 2.6.3 29 | */ 30 | package org.biouno.unochoice.issue69448; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue71909/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2024 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-71909. 27 | * 28 | * @since 2.8.4 29 | */ 30 | package org.biouno.unochoice.issue71909; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue72105/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-72105. 27 | * 28 | * @since 2.8.1 29 | */ 30 | package org.biouno.unochoice.issue72105; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue73239/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2025 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-73239. 27 | * 28 | * @since 2.8.7 29 | */ 30 | package org.biouno.unochoice.issue73239; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue74963/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2025 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-74963. 27 | * 28 | * @since 2.8.7 29 | */ 30 | package org.biouno.unochoice.issue74963; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue74967/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2025 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * See JENKINS-74967. 27 | * 28 | * @since 2.8.7 29 | */ 30 | package org.biouno.unochoice.issue74967; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue34818/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for global node properties issue. See JENKINS-34818. 27 | * 28 | * @since 1.5.x 29 | */ 30 | package org.biouno.unochoice.issue34818; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue38532/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2016 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for parameters with the equals separator. See JENKINS-38532. 27 | * 28 | * @since 1.5.x 29 | */ 30 | package org.biouno.unochoice.issue38532; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue48448/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for parameters with the equals separator. See JENKINS-48448. 27 | * 28 | * @since 2.1 29 | */ 30 | package org.biouno.unochoice.issue48448; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue49260/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for different folders having same Project name. See JENKINS-49260. 27 | * 28 | * @since 2.2 29 | */ 30 | package org.biouno.unochoice.issue49260; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue62215/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for input element with markup sanitation. See JENKINS-62215 27 | * 28 | * @since 2.4 29 | */ 30 | package org.biouno.unochoice.issue62215; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue51296/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | 26 | /** 27 | * Tests for projectName being correct after renaming project. See JENKINS-51296. 28 | * 29 | * @since 2.2 30 | */ 31 | package org.biouno.unochoice.issue51296; -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue63983/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2021 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for Groovy scripts with and without sandbox depending on approval. See JENKINS-63983 27 | * 28 | * @since 2.5.7 29 | */ 30 | package org.biouno.unochoice.issue63983; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue61068/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for radio parameter has incorrect default value on parambuild URL. See JENKINS-61068. 27 | * 28 | * @since 2.2.3 29 | */ 30 | package org.biouno.unochoice.issue61068; 31 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue65235/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2023 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Tests for accessing jenkinsProject context property on multibranch workflows. See JENKINS-65235. 27 | * 28 | * @since 2.6.5 29 | */ 30 | package org.biouno.unochoice.issue65235; 31 | 32 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/CascadeChoiceParameter/cascade-choice-parameter.js: -------------------------------------------------------------------------------- 1 | if (window.makeStaplerProxy) { 2 | window.__old__makeStaplerProxy = window.makeStaplerProxy; 3 | window.makeStaplerProxy = UnoChoice.makeStaplerProxy2; 4 | } 5 | 6 | window.addEventListener("DOMContentLoaded", () => { 7 | document.querySelectorAll(".cascade-choice-parameter-data-holder").forEach((dataHolder) => { 8 | const { name, paramName, randomName, proxyName } = dataHolder.dataset; 9 | const referencedParameters = dataHolder.dataset.referencedParameters; 10 | if (referencedParameters === undefined || referencedParameters === null || referencedParameters.length === 0) { 11 | console.log(`[${name}] - cascade-choice-parameters.js#querySelectorAll#forEach - No parameters referenced!`); 12 | return; 13 | } 14 | const referencedParametersList = dataHolder.dataset.referencedParameters.split(",").map((val) => val.trim()); 15 | const filterable = dataHolder.dataset.filterable === "true"; 16 | const filterLength = parseInt(dataHolder.dataset.filterLength); 17 | 18 | UnoChoice.renderCascadeChoiceParameter(`#${paramName}`, filterable, name, randomName, filterLength, paramName, referencedParametersList, window[proxyName]); 19 | }); 20 | 21 | if (window.makeStaplerProxy && window.__old__makeStaplerProxy) { 22 | window.makeStaplerProxy = window.__old__makeStaplerProxy; 23 | delete window["__old__makeStaplerProxy"]; 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /src/test/resources/org/biouno/unochoice/PipelineWithScriptlerParameters.groovy: -------------------------------------------------------------------------------- 1 | properties([ 2 | parameters([ 3 | [ 4 | $class: 'ChoiceParameter', 5 | choiceType: 'PT_SINGLE_SELECT', 6 | description: 'param001 description', 7 | filterLength: 1, 8 | filterable: true, 9 | name: 'param001', 10 | randomName: 'random-name', 11 | script: [ 12 | $class: 'ScriptlerScript', 13 | scriptlerScriptId: 'dummy.groovy', 14 | parameters: [ 15 | [name: 'arg1', value: 'bla'] 16 | ] 17 | ] 18 | ], 19 | [ 20 | $class: 'CascadeChoiceParameter', 21 | choiceType: 'PT_SINGLE_SELECT', 22 | description: 'param002 description', 23 | filterLength: 1, 24 | filterable: true, 25 | name: 'param002', 26 | randomName: 'random-name', 27 | referencedParameters: 'param001', 28 | script: [ 29 | $class: 'GroovyScript', 30 | script: [ 31 | $class: 'SecureGroovyScript', 32 | script: 'return [PARAM001]', 33 | sandbox: false 34 | ], 35 | fallbackScript: [ 36 | $class: 'SecureGroovyScript', 37 | script: 'return []', 38 | sandbox: false 39 | ] 40 | ] 41 | ] 42 | ]) 43 | ]) 44 | -------------------------------------------------------------------------------- /src/main/java/org/biouno/unochoice/model/ScriptDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.biouno.unochoice.model; 26 | 27 | import hudson.model.Descriptor; 28 | 29 | /** 30 | * Abstract descriptor for scripts. 31 | * 32 | * @author Bruno P. Kinoshita 33 | * @since 0.23 34 | */ 35 | public abstract class ScriptDescriptor extends Descriptor 39 | JENKINS-75194 40 | JENKINS-75194 41 | 42 | ENVIRONMENT 43 | PT_SINGLE_SELECT 44 | false 45 | 1 46 | 47 | 48 | ECR_IMAGE_TAG 49 | choice-parameter-aws-ecr-image-tag 50 | 1 51 | 60 | JENKINS-75194 61 | JENKINS-75194 62 | 63 | AWS_REGION 64 | PT_SINGLE_SELECT 65 | false 66 | 1 67 | 68 | 69 | 70 | 71 | 72 | 87 | true 88 | 89 | 90 | false 91 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue74967/TestFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2023 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.biouno.unochoice.issue74967; 25 | 26 | import org.biouno.unochoice.BaseUiTest; 27 | import org.junit.jupiter.api.Test; 28 | import org.jvnet.hudson.test.Issue; 29 | import org.jvnet.hudson.test.recipes.LocalData; 30 | import org.openqa.selenium.By; 31 | import org.openqa.selenium.WebElement; 32 | import org.openqa.selenium.support.ui.ExpectedConditions; 33 | import org.openqa.selenium.support.ui.Select; 34 | 35 | import java.util.List; 36 | 37 | import static org.junit.jupiter.api.Assertions.assertEquals; 38 | import static org.junit.jupiter.api.Assertions.assertTrue; 39 | 40 | /** 41 | * In JENKINS-74967 a JS exception when the user entered anything in the filter field. 42 | * The JavaScript code is not very well-designed (mea-culpa) so it is not easy to test 43 | * it. For that reason, the config.xml attached in this issue was used here to write a 44 | * complete e2e test (i.e. yes, we are killing the ant with an elephant). 45 | */ 46 | @Issue("JENKINS-74967") 47 | class TestFilter extends BaseUiTest { 48 | 49 | /** 50 | * Tests that the page loads with paramA=AAA, filter empty, and paramB showing AAA-1, AAA-2, and AAA-3. 51 | * Then, it enters the filter text BB, paramA is updated to BBB (matches filter), which cascades to 52 | * changing paramB to BBB-1, BBB-2, BBB-3. 53 | * 54 | * @throws Exception resolving the test web pages 55 | */ 56 | @Test 57 | @LocalData("test") 58 | void test() throws Exception { 59 | driver.get(j.getURL().toString() + "job/test/build"); 60 | 61 | wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".jenkins-spinner"))); 62 | 63 | WebElement paramA = findSelect("paramA"); 64 | assertTrue(paramA.isDisplayed()); 65 | assertTrue(paramA.isEnabled()); 66 | assertEquals("AAA", new Select(paramA).getFirstSelectedOption().getText()); 67 | 68 | List paramB = findRadios("paramB"); 69 | for (int i = 0; i < paramB.size(); i++) { 70 | WebElement param = paramB.get(i); 71 | assertTrue(getLabel(param).isDisplayed()); 72 | assertTrue(param.isEnabled()); 73 | assertEquals("AAA-" + (i + 1), param.getDomAttribute("value")); 74 | } 75 | 76 | WebElement filterElement = driver.findElement(By.cssSelector("div.active-choice[name='parameter'] > input.uno_choice_filter")); 77 | filterElement.sendKeys("BB"); 78 | 79 | wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".jenkins-spinner"))); 80 | 81 | paramA = findSelect("paramA"); 82 | assertTrue(paramA.isDisplayed()); 83 | assertTrue(paramA.isEnabled()); 84 | assertEquals("BBB", new Select(paramA).getFirstSelectedOption().getText()); 85 | 86 | paramB = findRadios("paramB"); 87 | for (int i = 0; i < paramB.size(); i++) { 88 | WebElement param = paramB.get(i); 89 | assertTrue(getLabel(param).isDisplayed()); 90 | assertTrue(param.isEnabled()); 91 | assertEquals("BBB-" + (i + 1), param.getDomAttribute("value")); 92 | } 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/js/lib/runner.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PhantomJS Runner QUnit Plugin 1.2.0 3 | * 4 | * PhantomJS binaries: http://phantomjs.org/download.html 5 | * Requires PhantomJS 1.6+ (1.7+ recommended) 6 | * 7 | * Run with: 8 | * phantomjs runner.js [url-of-your-qunit-testsuite] 9 | * 10 | * e.g. 11 | * phantomjs runner.js http://localhost/qunit/test/index.html 12 | */ 13 | 14 | /*global phantom:false, require:false, console:false, window:false, QUnit:false */ 15 | 16 | (function() { 17 | 'use strict'; 18 | 19 | var url, page, timeout, 20 | args = require('system').args; 21 | 22 | // arg[0]: scriptName, args[1...]: arguments 23 | if (args.length < 2 || args.length > 3) { 24 | console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite] [timeout-in-seconds]'); 25 | phantom.exit(1); 26 | } 27 | 28 | url = args[1]; 29 | page = require('webpage').create(); 30 | if (args[2] !== undefined) { 31 | timeout = parseInt(args[2], 10); 32 | } 33 | 34 | // Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`) 35 | page.onConsoleMessage = function(msg) { 36 | console.log(msg); 37 | }; 38 | 39 | page.onInitialized = function() { 40 | page.evaluate(addLogging); 41 | }; 42 | 43 | page.onCallback = function(message) { 44 | var result, 45 | failed; 46 | 47 | if (message) { 48 | if (message.name === 'QUnit.done') { 49 | result = message.data; 50 | failed = !result || !result.total || result.failed; 51 | 52 | if (!result.total) { 53 | console.error('No tests were executed. Are you loading tests asynchronously?'); 54 | } 55 | 56 | phantom.exit(failed ? 1 : 0); 57 | } 58 | } 59 | }; 60 | 61 | page.open(url, function(status) { 62 | if (status !== 'success') { 63 | console.error('Unable to access network: ' + status); 64 | phantom.exit(1); 65 | } else { 66 | // Cannot do this verification with the 'DOMContentLoaded' handler because it 67 | // will be too late to attach it if a page does not have any script tags. 68 | var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); }); 69 | if (qunitMissing) { 70 | console.error('The `QUnit` object is not present on this page.'); 71 | phantom.exit(1); 72 | } 73 | 74 | // Set a timeout on the test running, otherwise tests with async problems will hang forever 75 | if (typeof timeout === 'number') { 76 | setTimeout(function() { 77 | console.error('The specified timeout of ' + timeout + ' seconds has expired. Aborting...'); 78 | phantom.exit(1); 79 | }, timeout * 1000); 80 | } 81 | 82 | // Do nothing... the callback mechanism will handle everything! 83 | } 84 | }); 85 | 86 | function addLogging() { 87 | window.document.addEventListener('DOMContentLoaded', function() { 88 | var currentTestAssertions = []; 89 | 90 | QUnit.log(function(details) { 91 | var response; 92 | 93 | // Ignore passing assertions 94 | if (details.result) { 95 | return; 96 | } 97 | 98 | response = details.message || ''; 99 | 100 | if (typeof details.expected !== 'undefined') { 101 | if (response) { 102 | response += ', '; 103 | } 104 | 105 | response += 'expected: ' + details.expected + ', but was: ' + details.actual; 106 | } 107 | 108 | if (details.source) { 109 | response += "\n" + details.source; 110 | } 111 | 112 | currentTestAssertions.push('Failed assertion: ' + response); 113 | }); 114 | 115 | QUnit.testDone(function(result) { 116 | var i, 117 | len, 118 | name = ''; 119 | 120 | if (result.module) { 121 | name += result.module + ': '; 122 | } 123 | name += result.name; 124 | 125 | if (result.failed) { 126 | console.log('\n' + 'Test failed: ' + name); 127 | 128 | for (i = 0, len = currentTestAssertions.length; i < len; i++) { 129 | console.log(' ' + currentTestAssertions[i]); 130 | } 131 | } 132 | 133 | currentTestAssertions.length = 0; 134 | }); 135 | 136 | QUnit.done(function(result) { 137 | console.log('\n' + 'Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.'); 138 | 139 | if (typeof window.callPhantom === 'function') { 140 | window.callPhantom({ 141 | 'name': 'QUnit.done', 142 | 'data': result 143 | }); 144 | } 145 | }); 146 | }, false); 147 | } 148 | })(); -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue51296/TestProjectNameAfterRenaming.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.biouno.unochoice.issue51296; 26 | 27 | import java.io.IOException; 28 | import java.util.Map; 29 | 30 | import hudson.model.Descriptor; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertTrue; 33 | import org.biouno.unochoice.CascadeChoiceParameter; 34 | import org.biouno.unochoice.ChoiceParameter; 35 | import org.biouno.unochoice.model.GroovyScript; 36 | import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript; 37 | import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; 38 | import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; 39 | import org.junit.jupiter.api.BeforeEach; 40 | import org.junit.jupiter.api.Test; 41 | import org.jvnet.hudson.test.Issue; 42 | import org.jvnet.hudson.test.JenkinsRule; 43 | 44 | import hudson.model.FreeStyleProject; 45 | import hudson.model.ParametersDefinitionProperty; 46 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 47 | 48 | /** 49 | * Tests for projectName being correct after renaming project. See JENKINS-51296. 50 | * 51 | * @since 2.2 52 | */ 53 | @Issue("JENKINS-51296") 54 | @WithJenkins 55 | class TestProjectNameAfterRenaming { 56 | private JenkinsRule j; 57 | 58 | // LIST script 59 | private static final String SCRIPT_LIST = "return ['Test', jenkinsProject.getName()]"; 60 | private static final String FALLBACK_SCRIPT_LIST = "return ['EMPTY!']"; 61 | 62 | private static final String PARAMETER_NAME = "my-parameter-name"; 63 | 64 | private static final String PROJECT_NAME_BEFORE = "MyOldJenkinsJob"; 65 | private static final String PROJECT_NAME_AFTER = "MyRealJenkinsJob"; 66 | 67 | @BeforeEach 68 | void setUp(JenkinsRule j) { 69 | this.j = j; 70 | ScriptApproval.get() 71 | .preapprove(SCRIPT_LIST, GroovyLanguage.get()); 72 | ScriptApproval.get() 73 | .preapprove(FALLBACK_SCRIPT_LIST, GroovyLanguage.get()); 74 | } 75 | 76 | @Test 77 | void testProjectAreDifferent() throws IOException, Descriptor.FormException { 78 | 79 | FreeStyleProject project = j.createProject(FreeStyleProject.class, PROJECT_NAME_BEFORE); 80 | 81 | GroovyScript listScript = new GroovyScript(new SecureGroovyScript(SCRIPT_LIST, Boolean.FALSE, null), 82 | new SecureGroovyScript(FALLBACK_SCRIPT_LIST, Boolean.FALSE, null)); 83 | 84 | ChoiceParameter listParam = new ChoiceParameter(PARAMETER_NAME, "description...", "random-name", listScript, 85 | CascadeChoiceParameter.PARAMETER_TYPE_SINGLE_SELECT, false, 1); 86 | 87 | ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(listParam); 88 | 89 | project.addProperty(paramsDef); 90 | 91 | Map listSelectionValue = listParam.getChoices(); 92 | 93 | String choicesStatus = listParam.getChoicesAsString() ; 94 | 95 | // keys and values have the same content when the parameter returns an array... 96 | assertTrue(listSelectionValue.containsKey(PROJECT_NAME_BEFORE), "Wrong project name from the begging ["+choicesStatus+"] test broken?!"); 97 | 98 | // --- After renaming, the real test --- 99 | project.renameTo(PROJECT_NAME_AFTER); 100 | Map listSelectionValueAfter = listParam.getChoices(); 101 | 102 | choicesStatus = listParam.getChoicesAsString() ; 103 | 104 | // Now, check full name! 105 | assertTrue(listSelectionValueAfter.containsKey(PROJECT_NAME_AFTER), "Wrong project name after renaming: "+choicesStatus); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue38532/TestParameterValuesWithEquals.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.biouno.unochoice.issue38532; 25 | 26 | import hudson.model.Descriptor; 27 | 28 | import static org.junit.jupiter.api.Assertions.assertEquals; 29 | import org.biouno.unochoice.CascadeChoiceParameter; 30 | import org.biouno.unochoice.ChoiceParameter; 31 | import org.biouno.unochoice.DynamicReferenceParameter; 32 | import org.biouno.unochoice.model.GroovyScript; 33 | import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript; 34 | import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; 35 | import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; 36 | import org.junit.jupiter.api.BeforeEach; 37 | import org.junit.jupiter.api.Test; 38 | import org.jvnet.hudson.test.Issue; 39 | import org.jvnet.hudson.test.JenkinsRule; 40 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 41 | import org.kohsuke.stapler.HttpResponses; 42 | 43 | /** 44 | * Test that scripts can access global node properties. 45 | * 46 | * @since 1.5.x 47 | */ 48 | @Issue("JENKINS-38532") 49 | @WithJenkins 50 | class TestParameterValuesWithEquals { 51 | 52 | // LIST script 53 | private static final String SCRIPT_LIST = "return ['A=1', 'B=2', 'C=3']"; 54 | private static final String FALLBACK_SCRIPT_LIST = "return ['EMPTY!']"; 55 | 56 | // LIST_SELECTION script 57 | private static final String SCRIPT_LIST_SELECTION = "value = LIST.toString()\nreturn \"${value}\""; 58 | private static final String FALLBACK_SCRIPT_LIST_SELECTION = "return ['EMPTY!']"; 59 | 60 | @BeforeEach 61 | void setUp(JenkinsRule j) { 62 | ScriptApproval.get().preapprove(SCRIPT_LIST, GroovyLanguage.get()); 63 | ScriptApproval.get().preapprove(FALLBACK_SCRIPT_LIST, GroovyLanguage.get()); 64 | ScriptApproval.get().preapprove(SCRIPT_LIST_SELECTION, GroovyLanguage.get()); 65 | ScriptApproval.get().preapprove(FALLBACK_SCRIPT_LIST_SELECTION, GroovyLanguage.get()); 66 | } 67 | 68 | @Test 69 | void testEvaluationWorksEvenThoughWeUsedEqualsInParameterValues() throws Descriptor.FormException { 70 | GroovyScript listScript = new GroovyScript(new SecureGroovyScript(SCRIPT_LIST, Boolean.FALSE, null), 71 | new SecureGroovyScript(FALLBACK_SCRIPT_LIST, Boolean.FALSE, null)); 72 | GroovyScript listSelectionScript = new GroovyScript( 73 | new SecureGroovyScript(SCRIPT_LIST_SELECTION, Boolean.FALSE, null), 74 | new SecureGroovyScript(FALLBACK_SCRIPT_LIST_SELECTION, Boolean.FALSE, null)); 75 | ChoiceParameter listParam = new ChoiceParameter("LIST", "description...", "random-name1", listScript, 76 | CascadeChoiceParameter.PARAMETER_TYPE_SINGLE_SELECT, true, 1); 77 | DynamicReferenceParameter listSelectionParam = new DynamicReferenceParameter("LIST_SELECTION", "description...", 78 | "random-name2", listSelectionScript, CascadeChoiceParameter.ELEMENT_TYPE_FORMATTED_HIDDEN_HTML, "LIST", 79 | true); 80 | // should be a String 81 | String listValue = listParam.getDefaultParameterValue().getValue().toString(); 82 | try { 83 | listSelectionParam.doUpdate(String.format("%s=%s", listParam.getName(), listValue)); 84 | } catch (HttpResponses.HttpResponseException response) { 85 | // ignore 86 | } 87 | // as this is a formatted hidden HTML... 88 | String listSelectionValue = listSelectionParam.getChoicesAsString(); 89 | 90 | // by default, the plug-in returns the first element in the list... 91 | assertEquals("A=1", 92 | listSelectionValue, 93 | "Value returned from selection list doesn't match first element in list parameter"); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/jenkins_cert_1954/TestParametersXssVulnerabilities.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2021 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.biouno.unochoice.jenkins_cert_1954; 25 | 26 | import hudson.model.Descriptor; 27 | import org.htmlunit.html.*; 28 | import hudson.model.FreeStyleProject; 29 | import hudson.model.ParametersDefinitionProperty; 30 | import org.biouno.unochoice.ChoiceParameter; 31 | import org.biouno.unochoice.model.GroovyScript; 32 | import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript; 33 | import org.junit.jupiter.api.Test; 34 | import org.jvnet.hudson.test.JenkinsRule; 35 | import org.jvnet.hudson.test.JenkinsRule.WebClient; 36 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 37 | import org.xml.sax.SAXException; 38 | 39 | import java.io.IOException; 40 | 41 | import static org.junit.jupiter.api.Assertions.*; 42 | 43 | /** 44 | * Tests against XSS. See SECURITY-1954, and SECURITY-2008. 45 | * @since 2.5 46 | */ 47 | @WithJenkins 48 | class TestParametersXssVulnerabilities { 49 | 50 | /** 51 | * Tests that a {@code ChoiceParameter} using a Groovy script has its output value sanitized against XSS when 52 | * returning a List. 53 | * @throws IOException if it fails to load the script 54 | * @throws SAXException if the XML is malformed 55 | */ 56 | @Test 57 | void testChoicesParameterXss(JenkinsRule j) throws IOException, SAXException, Descriptor.FormException { 58 | String xssString = ""; 59 | FreeStyleProject project = j.createFreeStyleProject(); 60 | String scriptText = String.format("return '%s'", xssString); 61 | SecureGroovyScript secureScript = new SecureGroovyScript(scriptText, true, null); 62 | GroovyScript script = new GroovyScript(secureScript, secureScript); 63 | ChoiceParameter parameter = new ChoiceParameter( 64 | xssString, 65 | xssString, 66 | "random-name", 67 | script, 68 | ChoiceParameter.PARAMETER_TYPE_CHECK_BOX, 69 | false, 70 | 0); 71 | project.addProperty(new ParametersDefinitionProperty(parameter)); 72 | project.save(); 73 | 74 | 75 | try (WebClient wc = j.createWebClient()) { 76 | wc.setThrowExceptionOnFailingStatusCode(false); 77 | HtmlPage configPage = wc.goTo("job/" + project.getName() + "/build?delay=0sec"); 78 | DomNodeList nodes = configPage.getElementsByTagName("div"); 79 | DomElement renderedParameterElement = null; 80 | for (DomElement elem : nodes) { 81 | if (elem.getAttribute("class").contains("setting-main")) { 82 | renderedParameterElement = elem; 83 | break; 84 | } 85 | } 86 | assertNotNull(renderedParameterElement, "Could not locate rendered parameter element"); 87 | 88 | DomNode firstChild = null; 89 | for (DomNode child : renderedParameterElement.getChildren()) { 90 | // Spinner element must be ignored 91 | firstChild = child; 92 | if (child instanceof HtmlDivision && ((HtmlDivision) child).getAttribute("id").endsWith("-spinner")) { 93 | continue; 94 | } 95 | break; 96 | } 97 | assertNotNull(firstChild, "Could not locate first child element"); 98 | String renderedText = firstChild.asXml(); 99 | assertNotEquals(xssString, renderedText, "XSS string was not escaped!"); 100 | assertTrue(renderedText.trim().contains("&lt;img src=x onerror=alert(123)&gt;"), "XSS string was not escaped!"); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/resources/org/biouno/unochoice/common/radioContent.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 |
58 | 59 |
60 |
61 |
62 | 63 | 64 |
65 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/issue49260/TestProjectDifferenceAcrossFolders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.biouno.unochoice.issue49260; 26 | 27 | import java.io.IOException; 28 | import java.util.Map; 29 | 30 | import hudson.model.Descriptor; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertTrue; 33 | import org.biouno.unochoice.CascadeChoiceParameter; 34 | import org.biouno.unochoice.ChoiceParameter; 35 | import org.biouno.unochoice.model.GroovyScript; 36 | import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript; 37 | import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; 38 | import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; 39 | import org.junit.jupiter.api.BeforeEach; 40 | import org.junit.jupiter.api.Test; 41 | import org.jvnet.hudson.test.Issue; 42 | import org.jvnet.hudson.test.JenkinsRule; 43 | import org.jvnet.hudson.test.MockFolder; 44 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 45 | 46 | import hudson.model.FreeStyleProject; 47 | import hudson.model.ParametersDefinitionProperty; 48 | 49 | /** 50 | * Tests for different folders having same Project name. See JENKINS-49260. 51 | * 52 | * @since 2.2 53 | */ 54 | @Issue("JENKINS-49260") 55 | @WithJenkins 56 | class TestProjectDifferenceAcrossFolders { 57 | private JenkinsRule j; 58 | 59 | // LIST script 60 | private static final String SCRIPT_LIST = "return ['Test', jenkinsProject.getName(), jenkinsProject.getFullName()]"; 61 | private static final String FALLBACK_SCRIPT_LIST = "return ['EMPTY!']"; 62 | 63 | private static final String PARAMETER_NAME = "my-parameter-name"; 64 | 65 | private static final String PROJECT_NAME = "MyJenkinsJob"; 66 | private static final String FOLDER_NAME_A = "AAA"; 67 | private static final String FOLDER_NAME_B = "BBB"; 68 | 69 | @BeforeEach 70 | void setUp(JenkinsRule j) { 71 | this.j = j; 72 | ScriptApproval.get() 73 | .preapprove(SCRIPT_LIST, GroovyLanguage.get()); 74 | ScriptApproval.get() 75 | .preapprove(FALLBACK_SCRIPT_LIST, GroovyLanguage.get()); 76 | } 77 | 78 | @Test 79 | void testProjectsAreDifferent() throws IOException, Descriptor.FormException { 80 | GroovyScript listScript = new GroovyScript(new SecureGroovyScript(SCRIPT_LIST, Boolean.FALSE, null), 81 | new SecureGroovyScript(FALLBACK_SCRIPT_LIST, Boolean.FALSE, null)); 82 | 83 | MockFolder folderA = j.createFolder(FOLDER_NAME_A); 84 | MockFolder folderB = j.createFolder(FOLDER_NAME_B); 85 | 86 | FreeStyleProject projectA = folderA.createProject(FreeStyleProject.class, PROJECT_NAME); 87 | ChoiceParameter listParamA = new ChoiceParameter(PARAMETER_NAME, "description...", "random-name-A", listScript, 88 | CascadeChoiceParameter.PARAMETER_TYPE_SINGLE_SELECT, false, 1); 89 | projectA.addProperty(new ParametersDefinitionProperty(listParamA)); 90 | 91 | FreeStyleProject projectB = folderB.createProject(FreeStyleProject.class, PROJECT_NAME); 92 | ChoiceParameter listParamB = new ChoiceParameter(PARAMETER_NAME, "description...", "random-name-B", listScript, 93 | CascadeChoiceParameter.PARAMETER_TYPE_SINGLE_SELECT, false, 1); 94 | projectB.addProperty(new ParametersDefinitionProperty(listParamB)); 95 | 96 | Map listSelectionValueA = listParamA.getChoices(); 97 | Map listSelectionValueB = listParamB.getChoices(); 98 | 99 | // keys and values have the same content when the parameter returns an array... 100 | assertTrue(listSelectionValueA.containsKey(PROJECT_NAME), "Missing project name for A!"); 101 | assertTrue(listSelectionValueB.containsKey(PROJECT_NAME), "Missing project name for B!"); 102 | 103 | // Now, check full name! 104 | assertTrue(listSelectionValueA.containsKey(FOLDER_NAME_A+"/"+PROJECT_NAME), "Missing project full name for A!"); 105 | assertTrue(listSelectionValueB.containsKey(FOLDER_NAME_B+"/"+PROJECT_NAME), "Missing project full name for B!"); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/test/java/org/biouno/unochoice/jenkins_cert_2192/TestDynamicReferenceXss.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2021 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.biouno.unochoice.jenkins_cert_2192; 25 | 26 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 27 | import static org.junit.jupiter.api.Assertions.assertEquals; 28 | 29 | import java.io.IOException; 30 | import java.util.List; 31 | 32 | import hudson.model.Descriptor; 33 | import org.biouno.unochoice.AbstractCascadableParameter; 34 | import org.biouno.unochoice.ChoiceParameter; 35 | import org.biouno.unochoice.DynamicReferenceParameter; 36 | import org.biouno.unochoice.model.GroovyScript; 37 | import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript; 38 | import org.junit.jupiter.api.Test; 39 | import org.jvnet.hudson.test.Issue; 40 | import org.jvnet.hudson.test.JenkinsRule; 41 | import org.jvnet.hudson.test.JenkinsRule.WebClient; 42 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 43 | import org.xml.sax.SAXException; 44 | 45 | import org.htmlunit.CollectingAlertHandler; 46 | 47 | import hudson.model.FreeStyleProject; 48 | import hudson.model.ParametersDefinitionProperty; 49 | 50 | /** 51 | * Prevent a case where a DynamicReference parameter with a referenced 52 | * parameter name equal to {@code "+alert(123)+"} results in a possible 53 | * XSS case. 54 | * 55 | * @since 2.5.2 56 | * @see hudson.Util#escape(String) 57 | */ 58 | @Issue("2192") 59 | @WithJenkins 60 | class TestDynamicReferenceXss { 61 | 62 | /** 63 | * Tests that a {@code DynamicReference} reference parameter name is sanitized against XSS. 64 | * @throws IOException if it fails to load the script 65 | * @throws SAXException if the XML is malformed 66 | */ 67 | @Test 68 | void testChoicesParameterXss(JenkinsRule j) throws IOException, SAXException, Descriptor.FormException { 69 | FreeStyleProject project = j.createFreeStyleProject(); 70 | String scriptText = "return ['OK']"; 71 | SecureGroovyScript secureScript = new SecureGroovyScript(scriptText, true, null); 72 | GroovyScript script = new GroovyScript(secureScript, secureScript); 73 | 74 | final String xssString = "\"+alert(123)+\""; 75 | 76 | DynamicReferenceParameter parameter = new DynamicReferenceParameter( 77 | "PARAMETER_NAME", 78 | "Description", 79 | "random-name", 80 | script, 81 | ChoiceParameter.PARAMETER_TYPE_RADIO, 82 | xssString, 83 | false); 84 | project.addProperty(new ParametersDefinitionProperty(parameter)); 85 | project.save(); 86 | 87 | final CollectingAlertHandler alertHandler = new CollectingAlertHandler(); 88 | final WebClient wc = j.createWebClient(); 89 | wc.setThrowExceptionOnFailingStatusCode(false); 90 | wc.setAlertHandler(alertHandler); 91 | 92 | wc.goTo("job/" + project.getName() + "/build?delay=0sec"); 93 | final List alerts = alertHandler.getCollectedAlerts(); 94 | 95 | assertEquals(0, alerts.size(), "You got a JS alert, look out for XSS!"); 96 | } 97 | 98 | /** 99 | * Test that the reference parameter value is escaped. 100 | */ 101 | @Test 102 | void testGetReferencedParametersAsArray(JenkinsRule j) throws Descriptor.FormException { 103 | String scriptText = "return ['OK']"; 104 | SecureGroovyScript secureScript = new SecureGroovyScript(scriptText, true, null); 105 | GroovyScript script = new GroovyScript(secureScript, secureScript); 106 | final String xssString = "\"+alert(123)+\""; 107 | AbstractCascadableParameter parameter = new DynamicReferenceParameter( 108 | "PARAMETER_NAME", 109 | "Description", 110 | "random-name", 111 | script, 112 | ChoiceParameter.PARAMETER_TYPE_RADIO, 113 | xssString, 114 | false); 115 | 116 | String[] parameters = parameter.getReferencedParametersAsArray(); 117 | String[] expected = new String[] {""+alert(123)+""}; 118 | assertArrayEquals(expected, parameters, "Your reference parameter name was not escaped, look out for XSS!"); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/test/js/lib/qunit-1.14.0.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.14.0 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright 2013 jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2014-01-31T16:40Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 0 0.5em 2em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 0 0.5em 2.5em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | } 81 | 82 | /** Tests: Pass/Fail */ 83 | 84 | #qunit-tests { 85 | list-style-position: inside; 86 | } 87 | 88 | #qunit-tests li { 89 | padding: 0.4em 0.5em 0.4em 2.5em; 90 | border-bottom: 1px solid #FFF; 91 | list-style-position: inside; 92 | } 93 | 94 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 95 | display: none; 96 | } 97 | 98 | #qunit-tests li strong { 99 | cursor: pointer; 100 | } 101 | 102 | #qunit-tests li a { 103 | padding: 0.5em; 104 | color: #C2CCD1; 105 | text-decoration: none; 106 | } 107 | #qunit-tests li a:hover, 108 | #qunit-tests li a:focus { 109 | color: #000; 110 | } 111 | 112 | #qunit-tests li .runtime { 113 | float: right; 114 | font-size: smaller; 115 | } 116 | 117 | .qunit-assert-list { 118 | margin-top: 0.5em; 119 | padding: 0.5em; 120 | 121 | background-color: #FFF; 122 | 123 | border-radius: 5px; 124 | } 125 | 126 | .qunit-collapsed { 127 | display: none; 128 | } 129 | 130 | #qunit-tests table { 131 | border-collapse: collapse; 132 | margin-top: 0.2em; 133 | } 134 | 135 | #qunit-tests th { 136 | text-align: right; 137 | vertical-align: top; 138 | padding: 0 0.5em 0 0; 139 | } 140 | 141 | #qunit-tests td { 142 | vertical-align: top; 143 | } 144 | 145 | #qunit-tests pre { 146 | margin: 0; 147 | white-space: pre-wrap; 148 | word-wrap: break-word; 149 | } 150 | 151 | #qunit-tests del { 152 | background-color: #E0F2BE; 153 | color: #374E0C; 154 | text-decoration: none; 155 | } 156 | 157 | #qunit-tests ins { 158 | background-color: #FFCACA; 159 | color: #500; 160 | text-decoration: none; 161 | } 162 | 163 | /*** Test Counts */ 164 | 165 | #qunit-tests b.counts { color: #000; } 166 | #qunit-tests b.passed { color: #5E740B; } 167 | #qunit-tests b.failed { color: #710909; } 168 | 169 | #qunit-tests li li { 170 | padding: 5px; 171 | background-color: #FFF; 172 | border-bottom: none; 173 | list-style-position: inside; 174 | } 175 | 176 | /*** Passing Styles */ 177 | 178 | #qunit-tests li li.pass { 179 | color: #3C510C; 180 | background-color: #FFF; 181 | border-left: 10px solid #C6E746; 182 | } 183 | 184 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 185 | #qunit-tests .pass .test-name { color: #366097; } 186 | 187 | #qunit-tests .pass .test-actual, 188 | #qunit-tests .pass .test-expected { color: #999; } 189 | 190 | #qunit-banner.qunit-pass { background-color: #C6E746; } 191 | 192 | /*** Failing Styles */ 193 | 194 | #qunit-tests li li.fail { 195 | color: #710909; 196 | background-color: #FFF; 197 | border-left: 10px solid #EE5757; 198 | white-space: pre; 199 | } 200 | 201 | #qunit-tests > li:last-child { 202 | border-radius: 0 0 5px 5px; 203 | } 204 | 205 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 206 | #qunit-tests .fail .test-name, 207 | #qunit-tests .fail .module-name { color: #000; } 208 | 209 | #qunit-tests .fail .test-actual { color: #EE5757; } 210 | #qunit-tests .fail .test-expected { color: #008000; } 211 | 212 | #qunit-banner.qunit-fail { background-color: #EE5757; } 213 | 214 | 215 | /** Result */ 216 | 217 | #qunit-testresult { 218 | padding: 0.5em 0.5em 0.5em 2.5em; 219 | 220 | color: #2B81AF; 221 | background-color: #D2E0E6; 222 | 223 | border-bottom: 1px solid #FFF; 224 | } 225 | #qunit-testresult .module-name { 226 | font-weight: 700; 227 | } 228 | 229 | /** Fixture */ 230 | 231 | #qunit-fixture { 232 | position: absolute; 233 | top: -10000px; 234 | left: -10000px; 235 | width: 1000px; 236 | height: 1000px; 237 | } 238 | -------------------------------------------------------------------------------- /src/main/java/org/biouno/unochoice/ChoiceParameter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2020 Ioannis Moutsatsos, Bruno P. Kinoshita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.biouno.unochoice; 26 | 27 | import hudson.Extension; 28 | 29 | import org.apache.commons.lang.StringUtils; 30 | import org.biouno.unochoice.model.Script; 31 | import org.kohsuke.stapler.DataBoundConstructor; 32 | import org.jenkinsci.Symbol; 33 | 34 | import java.util.Objects; 35 | 36 | /** 37 | * A parameter that renders its options as a choice (select) HTML component. 38 | * 39 | * @author Bruno P. Kinoshita 40 | * @since 0.1 41 | */ 42 | public class ChoiceParameter extends AbstractScriptableParameter { 43 | 44 | /* 45 | * Serial UID. 46 | */ 47 | private static final long serialVersionUID = -4449319038169585222L; 48 | 49 | /** 50 | * Choice type. 51 | */ 52 | private final String choiceType; 53 | 54 | /** 55 | * Filter flag. 56 | */ 57 | private final Boolean filterable; 58 | 59 | /** 60 | * Filter length. Defines a minimum number of characters that must be entered before the filter 61 | * is activated. 62 | */ 63 | private final Integer filterLength; 64 | 65 | /** 66 | * Constructor called from Jelly with parameters. 67 | * 68 | * @param name name 69 | * @param description description 70 | * @param script script 71 | * @param choiceType choice type 72 | * @param filterable filter flag 73 | * @deprecated see JENKINS-32149 74 | */ 75 | @Deprecated 76 | public ChoiceParameter(String name, String description, Script script, String choiceType, Boolean filterable) { 77 | super(name, description, script); 78 | this.choiceType = StringUtils.defaultIfBlank(choiceType, PARAMETER_TYPE_SINGLE_SELECT); 79 | this.filterable = filterable; 80 | this.filterLength = null; 81 | } 82 | 83 | /** 84 | * Constructor called from Jelly with parameters. 85 | * @param name name 86 | * @param description description 87 | * @param randomName parameter random generated name 88 | * @param script script 89 | * @param choiceType choice type 90 | * @param filterable filter flag 91 | * @deprecated see JENKINS-31625 92 | */ 93 | @Deprecated 94 | public ChoiceParameter(String name, String description, String randomName, Script script, String choiceType, 95 | Boolean filterable) { 96 | super(name, description, randomName, script); 97 | this.choiceType = StringUtils.defaultIfBlank(choiceType, PARAMETER_TYPE_SINGLE_SELECT); 98 | this.filterable = filterable; 99 | this.filterLength = null; 100 | } 101 | 102 | /** 103 | * Constructor called from Jelly with parameters. 104 | * @param name name 105 | * @param description description 106 | * @param randomName parameter random generated name 107 | * @param script script 108 | * @param choiceType choice type 109 | * @param filterable filter flag 110 | * @param filterLength length when filter start filtering 111 | */ 112 | @DataBoundConstructor 113 | public ChoiceParameter(String name, String description, String randomName, Script script, String choiceType, 114 | Boolean filterable, Integer filterLength) { 115 | super(name, description, randomName, script); 116 | this.choiceType = StringUtils.defaultIfBlank(choiceType, PARAMETER_TYPE_SINGLE_SELECT); 117 | this.filterable = filterable; 118 | this.filterLength = filterLength; 119 | } 120 | 121 | /* 122 | * (non-Javadoc) 123 | * @see org.biouno.unochoice.AbstractUnoChoiceParameter#getChoiceType() 124 | */ 125 | @Override 126 | public String getChoiceType() { 127 | return this.choiceType; 128 | } 129 | 130 | /** 131 | * Get the filter flag. 132 | * @return filter flag 133 | */ 134 | public boolean getFilterable() { 135 | return Objects.equals(filterable, Boolean.TRUE); 136 | } 137 | 138 | /** 139 | * Get the filter length. 140 | * @return filter length 141 | */ 142 | public Integer getFilterLength() { 143 | return filterLength == null ? (Integer) 1 : filterLength; 144 | } 145 | 146 | // --- descriptor 147 | 148 | @Extension 149 | @Symbol({"activeChoice"}) 150 | public static final class DescriptImpl extends UnoChoiceParameterDescriptor { 151 | 152 | @Override 153 | public String getDisplayName() { 154 | return "Active Choices Parameter"; 155 | } 156 | 157 | @Override 158 | public String getHelpFile() { 159 | return "/plugin/uno-choice/help/parameter/active-choices-choice.html"; 160 | } 161 | } 162 | 163 | } 164 | --------------------------------------------------------------------------------