Documentation for JIRA 4.1. Documentation for other versions of JIRA is available too.
概要
You can control who can edit each field by makin small changes to the Velocity template files used to display fields in the Edit Issue screen.
One of the points of pain with JIRA is trying to control who can edit particular fields of an issue, as discussed in JRA-1330. Various suggestions have been made there, such as using a workflow, but the page How to create a new Custom Field Type gave me the idea of simply changing the velocity template that is used to display a field to control who can edit the field's values. This approach also provides enough flexibility to make other changes such as who is permitted read the contents of a field.
atlassian-jira/WEB-INF/classes/templates/jira/issue/field/*-edit.vm
, e.g. versions-edit.vm
in this casejira/src/java/com/atlassian/jira/issue/fields
for the field type you are interested in.versions-edit.vm
is used for both the Affects Versions and Fix Versions fields.fixVersions
. I actually found this out by simply tweaking the template to print out the $field.id, but it's really defined in atlassian-jira-enterprise-3.8-source/jira/src/java/com/atlassian/jira/issue/IIssueFieldConstants.java
.This example shows the changes made to versions-edit.vm
to control who can edit the Fix Versions field.
#controlHeader ($action $field.id $i18n.getText($field.nameKey) $fieldLayoutItem.required $displayParameters.get('noHeader'))
Here is where the changes start:
<!-- By default, the fields are writeable --> #set ($readonly = "no") #if ($field.id == "fixVersions") <!-- This example is restricting who can change the Fix Version to members of the fix-version-writers group --> #if ($authcontext.user.inGroup('fix-version-writers')) #set ($readonly = "no") #else #set ($readonly = "yes") #end #end
The following line is part of the original template
#if ($versions && !$versions.empty)
but these are the lines that change what is displayed. A "break" command would be useful in Velocity.
#if ($readonly == "yes") <!-- Display the field value --> #if ($currentVersions) #foreach ($cv in $currentVersions) #foreach ($version in $versions) #if ($cv == $version.key) $textutils.htmlEncode($version.value)<br> #end #end #end #else <!-- The Fix Version has not been set --> Unknown<br> #end
All the other lines in this file are unchanged except for the closing #end
line
#else <select multiple name="$field.id" size="#minSelectSize ($versions 1 6)" id="$field.id"> #if (!$fieldLayoutItem.required) <option value="$!unknownVersionId" #if ($currentVersions && $currentVersions.contains($!unknownVersionId))selected#end >$i18n.getText('common.words.unknown')</option> #end #foreach ($version in $versions) #if ($version.key == $unreleasedVersionId || $version.key == $releasedVersionId) #if ($optGroupOpen) </optgroup> #else #set ($optGroupOpen = true) #end <optgroup label="$textutils.htmlEncode($version.value)"> #else <option value="$!version.key" #if ($currentVersions && $version && $currentVersions.contains($version.key))selected#end >$textutils.htmlEncode($version.value)</option> #end #end #if ($optGroupOpen) </optgroup> #end </select> #end <!-- readonly --> #else $i18n.getText('common.words.unknown') #end #controlFooter ($action $fieldLayoutItem.getFieldDescription() $displayParameters.get('noHeader')) #if ($archivedVersions && !$archivedVersions.empty) #controlHeader ($action "" $i18n.getText($archivedVersionsTitle) false false) #foreach ($version in $archivedVersions) <a href="$req.getContextPath()/secure/IssueNavigator.jspa?reset=true&mode=hide&sorter/order=ASC&sorter/field=priority&pid=$project.getLong('id')&$archivedVersionsSearchParam=$version.id">$textutils.htmlEncode($version.name)#if ($velocityCount < $archivedVersions.size()),#end</a> #end #controlFooter ($action "" false) #end
In case that was a bit too detailed, here is the diff for JIRA 3.8.1:
[jira@toolsdev plugins]$ diff -c /data/jira/jira/atlassian-jira-enterprise-3.8-source/jira/src/etc/java/templates/jira/issue/field/versions-edit.vm ~/atlassian-jira-enterprise-3.8-standalone/atlassian-jira/WEB-INF/classes/templates/jira/issue/field/versions-edit.vm *** /data/jira/jira/atlassian-jira-enterprise-3.8-source/jira/src/etc/java/templates/jira/issue/field/versions-edit.vm 2007-03-09 15:49:33.000000000 -0800 --- /data/jira/atlassian-jira-enterprise-3.8-standalone/atlassian-jira/WEB-INF/classes/templates/jira/issue/field/versions-edit.vm 2007-07-04 09:24:52.000000000 -0700 *************** *** 1,6 **** --- 1,34 ---- #controlHeader ($action $field.id $i18n.getText($field.nameKey) $fieldLayoutItem.required $displayParameters.get('noHeader')) + <!-- By default, the fields are writeable --> + #set ($readonly = "no") + #if ($field.id == "fixVersions") + <!-- This example is restricting who can change the Fix Version to + members of the fix-version-writers group --> + #if ($authcontext.user.inGroup('fix-version-writers')) + #set ($readonly = "no") + #else + #set ($readonly = "yes") + #end + #end + #if ($versions && !$versions.empty) + #if ($readonly == "yes") + <!-- Display the field value --> + #if ($currentVersions) + #foreach ($cv in $currentVersions) + #foreach ($version in $versions) + #if ($cv == $version.key) + $textutils.htmlEncode($version.value)<br> + #end + #end + #end + #else + <!-- The Fix Version has not been set --> + Unknown<br> + #end + #else + <!-- All the other logic in this file is unchanged --> <select multiple name="$field.id" size="#minSelectSize ($versions 1 6)" id="$field.id"> #if (!$fieldLayoutItem.required) <option value="$!unknownVersionId" *************** *** 25,30 **** --- 53,59 ---- </optgroup> #end </select> + #end <!-- readonly --> #else $i18n.getText('common.words.unknown') #end
If you are having trouble with a hidden value being reset when the issue is edited, you can try passing it back like this:
<input type=hidden name="$customField.id" id="$customField.id" value="$value">
This may occur when a user with no write-permission for a select field edits the issue.