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

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

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

Edited
  • 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

0 votes
Answer accepted

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

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Apps & Integrations

🍻🍂Apptoberfest Update: Upcoming Virtual Events 🎉

Hello Community! I hope you've been enjoying the 🍂Apptoberfestivities🍂 (I know I have!) The event is heating up next week with a series of virtual events that we're calling the 🍻🍂Partner App ...

111 views 1 8
Read article

Community Events

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

Find an event

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

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you