Class JobGrantRequestAction

java.lang.Object
io.jenkins.plugins.batchcontrol.action.JobGrantRequestAction
All Implemented Interfaces:
Action, ModelObject

@Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) public class JobGrantRequestAction extends Object implements Action
Sidebar entry "Request Change Permission" on a job, linking to the grant request screen with this job already filled in (U-01).

Nothing about the change-control side of the plugin was discoverable from a job. Opening or saving /job/<name>/configure without an active permission window answers core's stock 403 "missing the Job/Configure permission", which says nothing about permission windows existing or about /batch-control/grants/ being where they are requested, and D-33 settled that intercepting that refusal page is not acceptable. The run side has no such problem because JobRequestAction puts "Request Run" on the sidebar. This makes the change side symmetric, and — the point of the fix — it is visible before the 403 rather than after it.

This action holds no URL space of its own: getUrlName() returns a link to the existing grant screen (relative to the job's URL, so it keeps the context path), pre-filling this job's full name (scopeFullName=<job>; D-71: the window names this job only, see GrantsSection.getPrefillScopeFullName), so the user lands on a form that is already about the job they came from. There is no view, no do* method and no state: every permission check that matters is the grant screen's own.

Who sees it

All three conditions must hold, so the entry appears exactly for the people it can help:
  1. change control is on — with the switch off there are no permission windows to request, and SPEC item 1 requires that no change-control UI appears (an acceptance criterion in its own right);
  2. the caller holds BatchControl/RequestGrant — without it the grant screen's own gate would refuse them, and advertising a link that 403s is the problem U-01 is about, not a fix for it;
  3. the caller does not already hold Item/Configure on this job. Offering "request permission" to someone who already has the permission is noise, and it would put the entry on every administrator's sidebar on every job. This also covers the caller whose window is open right now: while a granted window confers Item/Configure the entry is absent, and it comes back by itself when the window expires — which is the moment the user needs it.
The job page already requires Item/Read, so no further visibility check is needed. A job's sub-item (a matrix configuration, a Maven module) never shows it (D-82): it is configured through its parent job, where the entry is offered.
  • Field Details

    • REQUEST_CHANGE_LABEL

      public static final String REQUEST_CHANGE_LABEL
      Sidebar caption. Deliberately distinct from "Request Run" (U-02).
      See Also:
  • Constructor Details

    • JobGrantRequestAction

      public JobGrantRequestAction(Job<?,?> job)
  • Method Details

    • getJob

      public Job<?,?> getJob()
    • getIconFileName

      @CheckForNull public String getIconFileName()
      Specified by:
      getIconFileName in interface Action
    • getDisplayName

      public String getDisplayName()
      Specified by:
      getDisplayName in interface Action
      Specified by:
      getDisplayName in interface ModelObject
    • getUrlName

      public String getUrlName()
      A link to the grant screen rather than a sub-URL of the job, written relative to the job's own URL (../../batch-control/grants/?... for job/<name>/).

      Hosting review 2026-10-02: this used to be the root-relative /batch-control/grants/.... Core's classic sidebar (Functions.getActionUrl) prefixes such a name with the context path, but the app bar and menus of the new job page render Action.getEvent(), whose default is a link to getUrlName() that the page's script leaves untouched when it starts with / — so under a context path (/jenkins with mvn hpi:run) the entry led to /batch-control/... on the host and answered 404. Both renderers join a relative name to the job's URL (the classic one to <context>/<job.url>, the new one to the URL of the job in the current request, which AbstractItem.getUrl() also follows), so climbing one ../ per segment of the job URL lands on <context>/batch-control/ in both, in folders and under views alike. Overriding getEvent() instead would need LinkEvent, a @Restricted(Beta.class) API in the 2.568.x baseline.

      e2e-06 DEF-01: the URL carries one query parameter and no &. The new job page's menu escapes the event URL a second time, so & arrived as &amp; and the browser sent amp;scopeFullName, leaving the job unfilled. D-71: a window names one item and there is no scope type, so the full name is the only parameter the form needs. spec-review-S6 m-5: there is no actions parameter either; the form preselects CONFIGURE for a job (GrantsSection#isPrefillAction). This is the entry's one URL form, shared with FolderGrantRequestAction.

      No routing is added under /job/<name>/: a name containing ../ never matches a URL token. The full name is passed through Util.rawEncode(java.lang.String) because Functions.getActionUrl parses the value as a URI first and drops the sidebar entry if it does not parse — a job name containing a space would be enough.

      Specified by:
      getUrlName in interface Action
    • getDialogUrl

      public String getDialogUrl()
      D-66: root-relative URL of the dialog form, prefilled for this job (one query parameter, see getUrlName()). The classic sidebar entry (action.jelly) opens it in core's dialog.
    • getEvent

      public Event getEvent()
      D-66: on the new job page the entry opens the dialog form, as core's own "Build with Parameters" does (DialogEvent); the URL is relative to the job's URL.
      Specified by:
      getEvent in interface Action