Executing transition through groovyservice is failing due to anonymous user

We have a service which runs every 12 hours to transition issues where they meet certain criteria. The code is written in groovy which is attached. The code worked fine in JIRA 6.1.6 and a previous version of Scriptrunner but since our upgrade to JIRA 6.2.7 and 2.1.17 for Scriptrunner when we validate the workflow transition we receive an error:


2014-07-29 19:54:38,191 QuartzScheduler_Worker-0 ERROR ServiceRunner Dashboard Refresh onresolve.jira.groovy.refreshService THM-19 The anonymous user does not have permission to perform action on given issue.

The code is explicitly setting the user to an Admin who has access to transition this issue. I have done some debugging to ensure the user is being set correctly into the workflowTransitionUtil and everything seems to be OK.

code as follows:

import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.util.ErrorCollection
import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.util.JiraUtils
import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl
import org.apache.log4j.Category

import java.sql.Timestamp

log = Category.getInstance("com.onresolve.jira.groovy.refreshService")

try {
    User user = ComponentAccessor.getUserUtil().getUser('dashboard.refresh')
    ComponentManager componentManager = ComponentManager.getInstance()
    CustomFieldManager customFieldManager = componentManager.getCustomFieldManager()
    boolean wasIndexing = ImportUtils.isIndexIssues();
    ImportUtils.setIndexIssues(true);
    MutableIssue issue
    CustomField cf = customFieldManager.getCustomFieldObject("customfield_15405") //Auto Refresh??
    CustomField curCostcf = customFieldManager.getCustomFieldObject("customfield_15407") //Current Cost
    CustomField prevCostcf = customFieldManager.getCustomFieldObject("customfield_15406") //Previous Cost
    CustomField refCostcf = customFieldManager.getCustomFieldObject("customfield_15408") //Refresh Cost
    //Get user to transition the issues
    IssueManager issueManager = componentManager.getIssueManager()
    List TrancheKeys = componentManager.issueManager.getIssueIdsForProject(12500)
    List sprintKeys = componentManager.issueManager.getIssueIdsForProject(12300)
    List themeKeys = componentManager.issueManager.getIssueIdsForProject(12700)

    List mainList = []
    mainList.add(TrancheKeys)
    mainList.add(sprintKeys)
    mainList.add(themeKeys)
    Date today = new Date()
    int transitionID = -100
    for (l in mainList) {
        for (issueKey in l){
            //Load issue
            try {
                issue = issueManager.getIssueObject(issueKey)

                if (issue.getCustomFieldValue(cf).toString().toLowerCase() == 'yes') {

                    WorkflowTransitionUtil workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class );
                    workflowTransitionUtil.setIssue(issue);
                    workflowTransitionUtil.setUserkey('dashboard.refresh');

                    switch (issue.getProjectObject().id) {
                        case 12500:
                            transitionID = 21
                            break
                        case 12300:
                            transitionID = 11
                            break
                        case 12700:
                            transitionID = 11
                            break
                    }
                    if (transitionID != -100){

                        workflowTransitionUtil.setAction(transitionID)
                        ErrorCollection errorCollection = workflowTransitionUtil.validate()

                        if (errorCollection.hasAnyErrors()) {
                            log.error issue.key + ' ' + errorCollection.getErrorMessages()
                        }
                        else {
                            workflowTransitionUtil.progress();
                            if (issue.getProjectObject().id == 12700) {
                                //If monday
                                if (today.getAt(Calendar.DAY_OF_WEEK) == 2 && today.getAt(Calendar.AM_PM) == 0){    //Monday AM!!
                                  //  ModifiedValue prevVal = new ModifiedValue(issue.getCustomFieldValue(prevCostcf),issue.getCustomFieldValue(curCostcf) )
                                  //  prevCostcf.updateValue(null, issue, prevVal, new DefaultIssueChangeHolder())
                                    issue.setCustomFieldValue(prevCostcf, issue.getCustomFieldValue(curCostcf))
                                    issueManager.updateIssue(user,issue,EventDispatchOption.ISSUE_UPDATED, false)

                                    ModifiedValue  costVal = new ModifiedValue(issue.getCustomFieldValue(curCostcf), issue.getCustomFieldValue(refCostcf))
                                    curCostcf.updateValue(null, issue, costVal, new DefaultIssueChangeHolder())
                                }
                            }


                        }
                    }
                }
            } catch(all){
                log.error issue.key + ' Unknown error'
            }

        }
    }

ImportUtils.setIndexIssues(wasIndexing);

log.warn("Refresh Completed")

} catch(all) {
    log.error("Refresh did not complete successfully")
}

2 answers

1 accepted

0 vote

I think there is a big ugly bug in WorkflowTransitionUtilImpl. Although you can set the userKey, as you do, it's not actually used. Instead it checks the remote user.

Best thing is to rewrite your code to use IssueService. If you can't be bothered, you can try instantiating WTU yourself passing in an authentication context:

public WorkflowTransitionUtilImpl(JiraAuthenticationContext authenticationContext, WorkflowManager workflowManager, PermissionManager permissionManager, FieldScreenRendererFactory fieldScreenRendererFactory, CommentService commentService)

You can get the other services the normal way.
Best thing is to rewrite to use IssueService.

I will re-write using IssueService

Jamie is right but the simplest solution would be to put this before you call WorkflowTransitionUtil. 

authenticationContext.setLoggedInUser(user); 

Had the same issue, Transitioning with Issue Service is not perfect either, you still have to have a valid logged in user. This simple line solved everything, as when checking for the validity of transition it will check if the logged in user has permissions to do that action. 

It works perfectly with Herberts suggestion.

You need to make sure you reset the original user, as described here: https://scriptrunner.adaptavist.com/latest/jira/interacting-with-other-apps.html#_from_jira

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Bridget Sauer
Published Thursday in Marketplace Apps

Calling all developers––You're invited to Atlas Camp 2018

 Atlas Camp   is our developer event which will take place in Barcelona, Spain  from the 6th -7th of   September . This is a great opportunity to meet other developers and get n...

255 views 0 6
Read article

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