Custom field containing security levels as select list

 

I'm trying to populate a select list (on the create issue screen) populated with security levels . It is not appropriate to simply show the Security Level field (I understand that I can't simply rename it). I haven't been able to find a custom field type suitable.

Any help appreciated,

 

Thanks

 

2 answers

This widget could not be displayed.

You'll need to write a new field type to do that if you want to directly use the security levels.  Another option might be to create a standard select list and then script something that synchronises it with the security level list.

Out of curiosity, why do you need this?  I can think of only one use for it, and I'd probably take a different approach for that myself, but I'm keen to hear of other use-cases!

Hi Nick, thanks for the very swift reply!

 Here's a long-winded attempt at an explanation!

On our other system the security level is deliberately hidden, set automatically on issue creation according to the user's group membership (done via script runner). A custom field ('Group') is then autopopulated with the security level. The custom field naming has much more meaning to our users than 'Security Level'.

I would like to mimic this convention in the new Jira instance, whereby the user is able to select a Group value from a custom select list (choices being the security levels available), and then the security level is automatically set to this value following creation.

Is this the most up-to-date / suitable guide for custom field creation?

https://developer.atlassian.com/jiradev/jira-platform/guides/fields/tutorial-creating-a-custom-field-type

 

Thanks again

Hmm.  I'm not sure I understand that.  Could you not set the security level automatically on create, and then place the security level on edit screens for them to edit later?

That would reduce the problem to "we don't like the name 'security level'" which is completely understandable.  But you could put explanatory test with it, or, with a little "development", create a "translation" for your system that uses a different phrase (I say "development", but it's more "copy existing and do a search on some plain text")

It's important that the security level is *chosen* on creation I'm afraid. I've looked into a translation add-on* for Jira but wasn't able to work out how to use it with fields on the create issue form e.g. security level, issue.

*https://marketplace.atlassian.com/plugins/com.atlassian.translations.jira.inproduct/server/overview

Hang on, that's not what you said earlier - "set automatically on issue creation according to the user's group membership".

In the case where you want them to choose, you don't need the script, just stick it on the screen and make it mandatory.  Remember that JIRA will only let the user see and select a level that the user is in, so they can't get it too wrong.

Duh sorry, what I meant to say is the following:

The workaround at the moment is that the user has to choose the security level on the create screen (with a field description containing the user friendly name). The Group field is then autopopulated with the security level on the view screen.

 

I'm currently trying out Adam's Behaviour suggestion below.

This widget could not be displayed.

You could use a behaviour for this to create the options and then restrict the list.

Adapting the last example here could work for you.

I'd follow some of the examples from our documentation and see if behaviours would work for you.

You can get the various security levels for that project by using (for some reason I can't post formatted code so I've added it as below):

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.security.IssueSecuritySchemeManager

def issueSecurityLevelManager = ComponentAccessor.getIssueSecurityLevelManager()
def issueSecuritySchemeManager = ComponentAccessor.getComponent(IssueSecuritySchemeManager)

def srcProject = underlyingIssue.getProjectObject()
def issueSecurityScheme = issueSecuritySchemeManager.getSchemeFor(srcProject)

if (! issueSecurityScheme) {
log.warn("No issue security scheme defined for project ${srcProject.name}".toString())
return null
}

def securityLevels = issueSecurityLevelManager.getIssueSecurityLevels(issueSecurityScheme.id)

def securityLevelNames = securityLevels*.name

does this mean the script is run every single time any issue is updated? Is that practical?

Thanks Adam, I'm now able to populate a custom field with security levels using the code:

import com.atlassian.jira.security.groups.GroupManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.security.IssueSecurityLevel
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.security.IssueSecuritySchemeManager
import com.atlassian.jira.issue.security.IssueSecurityLevelManager
import com.atlassian.jira.component.ComponentAccessor

IssueSecuritySchemeManager issueSecuritySchemeManager = ComponentAccessor.getComponent(IssueSecuritySchemeManager.class)
IssueSecurityLevelManager issueSecurityLevelManager = ComponentAccessor.getComponent(IssueSecurityLevelManager.class)

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cField= customFieldManager.getCustomFieldObjectByName("Etest")
def issue = event.issue as Issue
def srcProject = issue.getProjectObject()
def issueSecurityScheme = issueSecuritySchemeManager.getSchemeFor(srcProject)

def optionsManager = ComponentAccessor.getOptionsManager()
def issueService = ComponentAccessor.getIssueService()

if (! issueSecurityScheme) {
log.warn("No issue security scheme defined for project ${srcProject.name}".toString())
return null
}

def securityLevels = issueSecurityLevelManager.getIssueSecurityLevels(issueSecurityScheme.id)
def securityLevelNames = securityLevels*.name
log.debug "sec level names: " + securityLevelNames

def fieldConfig = cField.getRelevantConfig(issue)
def currentOptions = optionsManager.getOptions(fieldConfig)

def newSecurityLevelNames = []

log.debug " current options: " + currentOptions

for (i in securityLevelNames){
log.debug i
if (!currentOptions.toString().contains(i)){
log.debug " new sec level " + i + " found "
newSecurityLevelNames.add(i)
}
}

for (i in newSecurityLevelNames){
def newSeqId = currentOptions*.sequence.max() - 1
optionsManager.createOption(fieldConfig, null, newSeqId, i.toString())
}

The list of security levels will be static so I will look to adapt this script to be run from the console as part of the Jira deployment, rather than running as a listener. Or is there any way I can setup the listener to trigger when a new security level (or the config is changed) is added?

What does the remaining code from the example do? Is this to update the create issue form on the fly?



def issueInputParameters = IssueService.newIssueInputParameters()

issueInputParameters.with {
addCustomFieldValue(faveFruitFld.idAsLong, option.optionId.toString())
addCustomFieldValue(faveFruitOtherFld.idAsLong,
null) }
def updateValidationResult = issueService.validateUpdate(currentUser, issue.id, issueInputParameters)
if (updateValidationResult.isValid()) {
issueService.update(currentUser, updateValidationResult) }
else {
log.warn(
"Failed to update issue: ${issue.key}: ${updateValidationResult.errorCollection}")
}

Thanks for your help

You should pull the security levels when you populate the list. That way they will keep in sync. The last part of that example was more to show you how to create new custom field options for your custom field in the current script you have. I see you already have that so you won't need anything else from that.

There is an IssueSecurityLevelAddedEvent in JIRA but we don't support those type of events in ScriptRunner at the moment. It could be done using behaviours which would allow the updated to be done automatically when a new security level is added.

Thanks Adam.

 

I've adapted my listener to work as a Behaviour (code is 99% the same), but nothing happens. The code below is added as the Initializer, and I've added appropriate workflow & field mapping to the Behaviour. I don't get anything written to the log - can you help? Also, I'd like this behaviour to trigger on "Edit Issue" also - is this a valid ActionName?

 

import com.atlassian.jira.security.groups.GroupManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.security.IssueSecurityLevel
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.security.IssueSecuritySchemeManager
import com.atlassian.jira.issue.security.IssueSecurityLevelManager
import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Logger
import org.apache.log4j.Level

// set a select list value -- also same for radio buttons
if (getActionName() != "Create Issue") {
return // not the initial action, so don't set default values
}

IssueSecuritySchemeManager issueSecuritySchemeManager = ComponentAccessor.getComponent(IssueSecuritySchemeManager.class)
IssueSecurityLevelManager issueSecurityLevelManager = ComponentAccessor.getComponent(IssueSecurityLevelManager.class)

def log = Logger.getLogger("com.apache.CreateSubTask")
log.setLevel(Level.DEBUG)

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cField= customFieldManager.getCustomFieldObjectByName("Entity")
//def issue = Issue
def srcProject = underlyingIssue?.getProjectObject()
def issueSecurityScheme = issueSecuritySchemeManager.getSchemeFor(srcProject)

def optionsManager = ComponentAccessor.getOptionsManager()
def issueService = ComponentAccessor.getIssueService()

if (! issueSecurityScheme) {
log.warn("No issue security scheme defined for project ${srcProject.name}".toString())
return null
}

def securityLevels = issueSecurityLevelManager.getIssueSecurityLevels(issueSecurityScheme.id)
def securityLevelNames = securityLevels*.name
log.debug "sec level names: " + securityLevelNames

def fieldConfig = cField.getRelevantConfig(getIssueContext())
def currentOptions = optionsManager.getOptions(fieldConfig)

def newSecurityLevelNames = []

log.debug " current options: " + currentOptions

for (i in securityLevelNames){
if (!currentOptions.toString().contains(i)){
newSecurityLevelNames.add(i)
}
}

def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueInputParameters = issueService.newIssueInputParameters()

for (i in newSecurityLevelNames){
def newSeqId = currentOptions*.sequence.max() - 1
def option = optionsManager.createOption(fieldConfig, null, newSeqId, i.toString())

}

Suggest an answer

Log in or Sign up to answer
Atlassian Summit 2018

Meet the community IRL

Atlassian Summit is an excellent opportunity for in-person support, training, and networking.

Learn more
Community showcase
Posted Aug 06, 2018 in Jira Service Desk

A is for Activate: Share your top Jira Service Desk onboarding tips for new users!

Hi, everyone! Molly here from the Jira Service Desk Product Marketing Team :).  In the spirit of this month's  august-challenge, we're sourcing stories of Jira Service Desk activation fro...

565 views 25 15
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you