Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

ScriptRunner Behaviours setting "read only" to all statements, can't set/clear error

Lacey McDonnell December 10, 2020
  • Problem Statements
    • I cannot figure out why the read-only section is applying to all statements; it's even locking for Jira-Administrators group even though it's not applied to that statement (from what I can tell)
    • How can I set the error message on the Issue Type field, to be cleared if another project is selected?
    • Can this script be further optimized to improve performance? I'm sure I've got repeats and stragglers.

 

  • Already Tried
    • Removing the getFieldById(ISSUE_TYPE).with setting from individual statements and move to end
    • Adding different settings to each statement (i.e. some are TRUE while others are FALSE)
    • Adding setError and clearError to each statement
    • Adding setError and clearError to the end
    • Combining the remoteUsersRoles into a single statement but it wound up reading none of them (e.g. if ["Project Managers","Program Managers","Team Leads"] in remoteUsersRoles)

 

Thanks in advance to anyone who can help!

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.security.roles.ProjectRoleManager
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import static com.atlassian.jira.issue.IssueFieldConstants.ISSUE_TYPE

@BaseScript Field Behaviours fieldBehaviours

def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
def allIssueTypes = ComponentAccess.constantsManager.allIssueTypeObjects
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def issueTypeField = getFieldByID(ISSUE_TYPE)
def remoteUsersRoles = projectRoleManager.getProjectRoles(user, issueContext,projectObject)*.name
def availableIssueTypes = []

def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

if (ComponentAccessor.getGroupManager().isUserInGroup(currentUser, "jira-administrators")) {
availableIssueTypes.allAll(allIssueTypes.findAll {it.name in ["Initiative", "Bug","Story","Task","Epic","Problem","Incident"] })
}

if ("Project Managers" in remoteUsersRoles) {
availableIssueType.addAll(allIssueTypes.findAll {it.name in ["Initiative"] })
}

if ("Program Managers" in remoteUsersRoles) {
availableIssueType.addAll(allIssueTypes.findAll {it.name in ["Initiative"] })
}

if ("Administrators" in remoteUsersRoles) {
availableIssueType.addAll(allIssueTypes.findAll {it.name in ["Initiative"] })
}

if ("TRelease Coordinators" in remoteUsersRoles) {
def constantsManager = ComponentAccessor.getConstantsManager()
def queryIssueType = constantsManager.getAllIssueTypeObjects().find {it.name == "Sub-task" }
getFieldByID(ISSUE_TYPE).with {
setFormValue(queryIssueType.id)
setReadOnly(true)
}
}

if ("Team Leads" in remoteUsersRoles) {
def constantsManager = ComponentAccessor.getConstantsManager()
def queryIssueType = constantsManager.getAllIssueTypeObjects().find {it.name == "Sub-task" }
getFieldByID(ISSUE_TYPE).with {
setFormValue(queryIssueType.id)
setReadOnly(true)
}
}

if ("Developers" in remoteUsersRoles) {
def constantsManager = ComponentAccessor.getConstantsManager()
def queryIssueType = constantsManager.getAllIssueTypeObjects().find {it.name == "Sub-task" }
getFieldByID(ISSUE_TYPE).with {
setFormValue(queryIssueType.id)
setReadOnly(true)
}
}

if ("Testers" in remoteUsersRoles) {
def constantsManager = ComponentAccessor.getConstantsManager()
def queryIssueType = constantsManager.getAllIssueTypeObjects().find {it.name == "Sub-task" }
getFieldByID(ISSUE_TYPE).with {
setFormValue(queryIssueType.id)
setReadOnly(true)
}
}

issueTypeField.setFieldOptions(availableIssueTypes)

 

1 answer

1 accepted

Suggest an answer

Log in or Sign up to answer
0 votes
Answer accepted
Peter-Dave Sheehan
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 14, 2021

Hi @Lacey McDonnell 

First, in order to have issueType behaviour be reset when you change projects, you behaviour project mapping needs to be set to "All Projects" and "All Issue Types".

Otherwise, the script only fires in the mapped project, and doesn't reset when you change the project unless you close and re-open the form.

Then, your script has to decide whether to apply or clear the behaviour.

The challenge with that is if you have other scripts/configs that touch on the issueType, you will need to combine them all into one so you don't have conflicting rules.

 

Now, you asked about ideas for simplifying or avoiding redundancy ... and preventing the read-only statements from running on admins and other roles ... here is a re-written script (untested) that might achieve all your goals.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.security.roles.ProjectRoleManager
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import static com.atlassian.jira.issue.IssueFieldConstants.ISSUE_TYPE

//@BaseScript Field Behaviours fieldBehaviours

def groupManager = ComponentAccessor.groupManager
def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager)
//useing project-specific issue types instead of all issue types from your instance.
def allIssueTypes = ComponentAccessor.issueTypeSchemeManager.getIssueTypesForProject(issueContext.projectObject)
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def issueTypeField = getFieldById(ISSUE_TYPE)
def remoteUsersRoles = projectRoleManager.getProjectRoles(user, issueContext.projectObject)*.name
def availableIssueTypes = []

def projectParams = [
[
pkey: 'ABC', //the key to a project where the following parameters should be applicable
groupTypeMap:[
groups: ['jira-administrators'],
types: ["Initiative", "Bug","Story","Task","Epic","Problem","Incident"]
],
roleTypeMap: [
limit : [
roles: ['Project Managers', 'Program Manager', 'Administrators'],
types: ['Initiative'],
],
set : [
roles: ['TRelease Coordinators','Team Leads', 'Developers', 'Testers'],
type: 'Sub-Task'
]
]
],
//add other project block like the one above if necessary
]
def projectParam = projectParams.find{it.pkey == issueContext.projectObject.key}
if(projectParam){
if(projectParam.groupTypeMap.groups.any{ groupManager.isUserInGroup(currentUser, it as String)}){
availableIssueTypes.addAll(allIssueTypes.findAll{it.name in projectParam.groupTypeMap.types})
issueTypeField.setFieldOptions(availableIssueTypes)
} else {
if(projectParam.roleTypeMap.limit.roles.any{it in remoteUsersRoles}){
availableIssueTypes.addAll(allIssueTypes.findAll{it.name in projectParam.roleTypeMap.limit.types})
} else {
if(projectParam.roleTypeMap.set.roles.any{it in remoteUsersRoles}){
issueTypeField.setReadOnly(true).setFormValue(allIssueTypes.find{ it.name == projectParam.roleTypeMap.set.type}.id)
return //we don't need to process/adjust availableIssueType if the field is read-only
}
}
}
issueTypeField.setFieldOptions(availableIssueTypes)
} else {
//not a controlled project ... reset everything
issueTypeField.with{
setReadOnly(false)
setFieldOptions(allIssueTypes) //not sure if this is necessary. The field options should get re-loaded when you change project
}

You will see that I collapsed all the repeats into a single set of logic.. and added a priority order by first checking if the user is in a group, then checking the role for limiting the list and finally checking the role for setting the value. So the next condition is only evaluated if the first one fails.

A lot of this is based on the data structure in projectParams. This put the data you want the logic to be based on to be separate from where the logic is evaluated. This way, you can just add new roles or issuetypes in the correct place without having to write new blocks of code.

If you needed to deploy a separate set of rules for another project, you should be able to, in theory, just add another block in the data structure.

Hope this helps

TAGS
AUG Leaders

Atlassian Community Events