Executing transition through groovyservice is failing due to anonymous user

Dean Ashton July 29, 2014

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 votes
Answer accepted
JamieA
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.
July 29, 2014

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.
Dean Ashton July 29, 2014

I will re-write using IssueService

2 votes
Herberts Markūns December 22, 2014

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. 

Ramesh Udari1 November 29, 2016

It works perfectly with Herberts suggestion.

JamieA
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.
November 30, 2016

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
TAGS
AUG Leaders

Atlassian Community Events