ScriptRunner transition as wrong user

Andrew Culver
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.
February 9, 2017

JIRA 6.3.13

ScriptRunner 4.1.3.4

I have a script which is running on a transition in our Helpdesk (HD) project that tries to transition the status of a linked issue in our Windows Server Support Team (WSST) project. The script should be performing the transition as the user "jirabot" which is a non-person user in the automaticservices group, which has wide permissions to do pretty much anything in every project.

When the user cgreco9 transitions the HD ticket which fires off the ScriptRunner script, I get an error in the logs saying that the user cgreco9 doesn't have permission to transition the WSST ticket. This is true, she doesn't have permission, but the transition should be performed by jirabot, not the user. Why and how can I fix this?

Here is my script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
def issueService = ComponentAccessor.getIssueService()
def linkType = ["Escalated"]
// 6.x validateTransition wants a User, so we have to use .getDirectoryUser()
// 7.x validateTransition wants an ApplicationUser, so remove the .getDirectoryUser() after we upgrade
//def transUsers = ComponentAccessor.getJiraAuthenticationContext().getUser().getDirectoryUser()
def transUsers = ComponentAccessor.getUserManager().getUserByName("jirabot").getDirectoryUser()
def linkMgr = ComponentAccessor.getIssueLinkManager()
// Look through the issue links
// If we're starting on an issue with a link that says "escalated to", then use:
//     getInwardLinks(issue.id)
//     getSourceObject()
// If we're starting on an issue with a link that says "escalated from", then use:
//     getOutwardLinks(issue.id)
//     getDestinationObject()
for (IssueLink link in linkMgr.getInwardLinks(issue.id)) {
    def linkedIssue = link.getSourceObject()
    // Does the name of the link match "Escalated" ?
    if (linkType.contains(link.issueLinkType.name)) {
        def destStatusObject = linkedIssue.getStatusObject()
	// Is the status of the linked issue "Signs Needed" ?
        if (destStatusObject.name == "Signs Needed") {
            // Prepare our input for the transition
            def issueInputParameters = issueService.newIssueInputParameters()
            issueInputParameters.with {
                setComment("CCPS has posted signs. Cameras can now be activated.")
                //setSkipScreenCheck(true)
            }
            // Validate transitioning the linked issue to "Signs Needed"
            def validationResult = issueService.validateTransition(transUsers, linkedIssue.id, 61, issueInputParameters)
            if (validationResult.isValid()) {
                // Perform the transition
                def issueResult = issueService.transition(transUsers, validationResult)
                if (! issueResult.isValid()) {
                    log.warn("Failed to transition task ${linkedIssue.key}, errors: ${issueResult.errorCollection}")
                }
            } else {
                log.warn("Could not transition task ${linkedIssue.key}, errors: ${validationResult.errorCollection}")
            }
        } else {
            log.warn("Skipping link: ${link.issueLinkType.name} ${linkedIssue.key} ${destStatusObject.name} (wrong status)")
        }
    } else {
        log.warn("Skipping link: ${link.issueLinkType.name} ${linkedIssue.key} (wrong type)")
    }
}

 

And here is the error:

2017-01-31 11:31:16,426 http-bio-8080-exec-59 WARN cgreco9 691x1295970x1 1aed2mk 172.18.58.5 /secure/CommentAssignIs
sue.jspa [scriptrunner.jira.workflow.ScriptWorkflowFunction] Could not transition task WSST-7603, errors: Errors: {}
Error Messages: [Christine Greco, you do not have the permission to comment on this issue.]

3 answers

1 accepted

0 votes
Answer accepted
Andrew Culver
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.
May 17, 2018

This is no longer a problem since upgrading to Jira 7.7.1.

Alexey Rjeutski May 17, 2018

Well, for Jira 7.4.3 is not working yet) but workaround works.

1 vote
Thanos Batagiannis _Adaptavist_
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.
February 15, 2017

Hi Andrew, 

I use the following function for transit an issue, give it a go. The cwdUser will be the author of the comment. And of course make sure, as Vasiliy said, that this user has the right permissions,

def transitIssue(Issue issue, int actionId, ApplicationUser cwdUser) {
    def issueService = ComponentAccessor.getIssueService()

    IssueInputParameters issueInputParameters = issueService.newIssueInputParameters()
    issueInputParameters.setComment("This is a comment")
    issueInputParameters.setSkipScreenCheck(true)

    def transitionOptions= new TransitionOptions.Builder()
        .skipConditions()
        .skipPermissions()
        .skipValidators()
        .build()

    def transitionValidationResult =
        issueService.validateTransition(cwdUser, issue.id, actionId, issueInputParameters, transitionOptions)

    if (transitionValidationResult.isValid()) {
        return issueService.transition(cwdUser, transitionValidationResult).getIssue()
    }

    log.error "Transition of issue ${issue.key} failed. " + transitionValidationResult.errorCollection
}

regards, Thanos

Alexey Rjeutski May 17, 2018

It looks like the JIRA bug with DefaultIssueService, seems the user parameter is ignored for validateTransition when the comment is added within the inputParameters inside the transition and the user is got from the session. Only skipPermissions option helps.

0 votes
Vasiliy Zverev
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.
February 9, 2017

Into postfunction a comment is added (see line

setComment("CCPS has posted signs. Cameras can now be activated.")
)

But Christine Greco does not have a permission to comment WSST-7603.

Options:

  • make sure that all users able to do this transition have permission to comment issue
  • add check for comment issue permission
Andrew Culver
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.
February 10, 2017

Hi Vasiliy,

Why would it be trying to add the comment as Christine rather than as jirabot?

I have another almost identical script (below) which does the same thing as the script above, except it is run from the WSST ticket and updates the HD ticket. This script works fine and is able to add a comment as jirabot. I can see in the HD ticket that the comment is added by jirabot, not the person performing the action.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
def issueService = ComponentAccessor.getIssueService()
def linkType = ["Escalated"]
// 6.x validateTransition wants a User, so we have to use .getDirectoryUser()
// 7.x validateTransition wants an ApplicationUser, so remove the .getDirectoryUser() after we upgrade
//def user = ComponentAccessor.getJiraAuthenticationContext().getUser().getDirectoryUser()
def user = ComponentAccessor.getUserManager().getUserByName("jirabot").getDirectoryUser()
def linkMgr = ComponentAccessor.getIssueLinkManager()
// Look through the outward links
for (IssueLink link in linkMgr.getOutwardLinks(issue.id)) {
    def destIssue = link.getDestinationObject()
    // Does the name of the link match "Escalated" ?
    if (linkType.contains(link.issueLinkType.name)) {
        def destStatusObject = destIssue.getStatusObject()
	// Is the status of the linked issue "Installing" ?
        if (destStatusObject.name == "Installing") {
            // Prepare our input for the transition
            def issueInputParameters = issueService.newIssueInputParameters()
            issueInputParameters.with {
                setComment("Camera has been installed. Signs are needed before camera can be activated.")
                //setSkipScreenCheck(true)
            }
            // Validate transitioning the linked issue to "Signs Needed"
            def validationResult = issueService.validateTransition(user, destIssue.id, 41, issueInputParameters)
            if (validationResult.isValid()) {
                // Perform the transition
                def issueResult = issueService.transition(user, validationResult)
                if (! issueResult.isValid()) {
                    log.warn("Failed to transition task ${destIssue.key}, errors: ${issueResult.errorCollection}")
                }
            } else {
                log.warn("Could not transition task ${destIssue.key}, errors: ${validationResult.errorCollection}")
            }
        } else {
            log.warn("Skipping link: ${link.issueLinkType.name} ${destIssue.key} ${destStatusObject.name} (wrong status)")
        }
    } else {
        log.warn("Skipping link: ${link.issueLinkType.name} ${destIssue.key} (wrong type)")
    }
}
Vasiliy Zverev
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.
February 12, 2017

There is a permission to cemment issue. Try to check this permission for both issues.

Andrew Culver
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.
February 24, 2017

Hi Vasiliy,

What I'm trying to get at is: the comment should be added by the jirabot user, not the current user. I'm not concerned about the permission of the current user being able to comment, because that user shouldn't have permission to comment on the linked issue and I don't want them commenting on it. I want the comment to be posted by jirabot.

Vasiliy Zverev
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.
February 26, 2017

It seems that you should use Commentmanager to do this. Here is code example:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.comments.CommentManager

Issue issue;
ComponentAccessor.getCommentManager().create(
      issue,
        ComponentAccessor.getUserManager().getUserByName("jirabot")
        , "Camera has been installed. Signs are needed before camera can be activated."
        , false
        
)
Andrew Culver
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.
March 3, 2017

Hi Vasiliy,

Thanks for the suggestion. I have modified the code to add the comment using the CommentManager after the transition. It is now correctly adding a comment by jirabot, and the activity log of the ticket shows that the status changed to Activation Needed (good) but the status of the ticket still shows up as Signs Needed (bad). Do I need to force a reindex or something?

Here's what I changed:

[jira@jig scripts]$ diff -u camera-install-hd-signs-posted-transitions-wsst-to-activation-needed.groovy.saved camera-install-hd-signs-posted-transitions-wsst-to-activation-needed.groovy      
--- camera-install-hd-signs-posted-transitions-wsst-to-activation-needed.groovy.saved	2017-03-02 16:54:54.080170727 -0500
+++ camera-install-hd-signs-posted-transitions-wsst-to-activation-needed.groovy	2017-03-03 11:23:59.842001870 -0500
@@ -1,5 +1,6 @@
 import com.atlassian.jira.component.ComponentAccessor
 import com.atlassian.jira.issue.link.IssueLink
+import com.atlassian.jira.issue.comments.CommentManager
 
 def issueService = ComponentAccessor.getIssueService()
 def linkType = ["Escalated"]
@@ -33,7 +34,7 @@
             // Prepare our input for the transition
             def issueInputParameters = issueService.newIssueInputParameters()
             issueInputParameters.with {
-                setComment("CCPS has posted signs. Cameras can now be activated.")
+                //setComment("CCPS has posted signs. Cameras can now be activated.")
                 //setSkipScreenCheck(true)
             }
 
@@ -45,7 +46,14 @@
                 def issueResult = issueService.transition(transUsers, validationResult)
                 if (! issueResult.isValid()) {
                     log.warn("Failed to transition task ${linkedIssue.key}, errors: ${issueResult.errorCollection}")
-                }
+                } else {
+			// Comment on the linked issue
+			ComponentAccessor.getCommentManager().create(
+				linkedIssue, 
+				ComponentAccessor.getUserManager().getUserByName("jirabot"),
+				"CCPS has posted signs. Cameras can now be activated.", 
+				false )
+		}
             } else {
                 log.warn("Could not transition task ${linkedIssue.key}, errors: ${validationResult.errorCollection}")
             }

Here's the full current script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.comments.CommentManager
def issueService = ComponentAccessor.getIssueService()
def linkType = ["Escalated"]
// 6.x validateTransition wants a User, so we have to use .getDirectoryUser()
// 7.x validateTransition wants an ApplicationUser, so remove the .getDirectoryUser() after we upgrade
//def transUsers = ComponentAccessor.getJiraAuthenticationContext().getUser().getDirectoryUser()
def transUsers = ComponentAccessor.getUserManager().getUserByName("jirabot").getDirectoryUser()
def linkMgr = ComponentAccessor.getIssueLinkManager()
// Look through the issue links
// If we're starting on an issue with a link that says "escalated to", then use:
//     getInwardLinks(issue.id)
//     getSourceObject()
// If we're starting on an issue with a link that says "escalated from", then use:
//     getOutwardLinks(issue.id)
//     getDestinationObject()
for (IssueLink link in linkMgr.getInwardLinks(issue.id)) {
    def linkedIssue = link.getSourceObject()
    // Does the name of the link match "Escalated" ?
    if (linkType.contains(link.issueLinkType.name)) {
        def destStatusObject = linkedIssue.getStatusObject()
	// Is the status of the linked issue "Signs Needed" ?
        if (destStatusObject.name == "Signs Needed") {
            // Prepare our input for the transition
            def issueInputParameters = issueService.newIssueInputParameters()
            issueInputParameters.with {
                //setComment("CCPS has posted signs. Cameras can now be activated.")
                //setSkipScreenCheck(true)
            }
            // Validate transitioning the linked issue to "Signs Needed"
            def validationResult = issueService.validateTransition(transUsers, linkedIssue.id, 61, issueInputParameters)
            if (validationResult.isValid()) {
                // Perform the transition
                def issueResult = issueService.transition(transUsers, validationResult)
                if (! issueResult.isValid()) {
                    log.warn("Failed to transition task ${linkedIssue.key}, errors: ${issueResult.errorCollection}")
                } else {
			// Comment on the linked issue
			ComponentAccessor.getCommentManager().create(
				linkedIssue, 
				ComponentAccessor.getUserManager().getUserByName("jirabot"),
				"CCPS has posted signs. Cameras can now be activated.", 
				false )
		}
            } else {
                log.warn("Could not transition task ${linkedIssue.key}, errors: ${validationResult.errorCollection}")
            }
        } else {
            log.warn("Skipping link: ${link.issueLinkType.name} ${linkedIssue.key} ${destStatusObject.name} (wrong status)")
        }
    } else {
        log.warn("Skipping link: ${link.issueLinkType.name} ${linkedIssue.key} (wrong type)")
    }
}
Vasiliy Zverev
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.
March 5, 2017

Yes, reindex should be added to show correct values. 

Andrew Culver
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.
March 6, 2017

Forgive my ignorance... I've added the following, but it's behaving the same (adds comment and issue activity log shows the status changed, but status field still has the old value). Nothing written to the logs.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.comments.CommentManager
import com.atlassian.jira.util.ImportUtils


...
 
            // Validate transitioning the linked issue to "Signs Needed"
            def validationResult = issueService.validateTransition(transUsers, linkedIssue.id, 61, issueInputParameters)
            if (validationResult.isValid()) {
                // Perform the transition
                def issueResult = issueService.transition(transUsers, validationResult)
                if (! issueResult.isValid()) {
                    log.warn("Failed to transition task ${linkedIssue.key}, errors: ${issueResult.errorCollection}")
                } else {
                        // Comment on the linked issue
                        ComponentAccessor.getCommentManager().create(
                                linkedIssue,
                                ComponentAccessor.getUserManager().getUserByName("jirabot"),
                                "CCPS has posted signs. Cameras can now be activated.",
                                false )
                        boolean wasIndexing = ImportUtils.isIndexIssues()
                        ImportUtils.setIndexIssues(true)
                        ComponentAccessor.getIssueIndexManager().reIndex(linkedIssue)
                        ImportUtils.setIndexIssues(wasIndexing);
                }
            } else {
                log.warn("Could not transition task ${linkedIssue.key}, errors: ${validationResult.errorCollection}")
            }
Vasiliy Zverev
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.
March 6, 2017
Andrew Culver
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.
March 7, 2017

We're actually still running 6.3.13. An upgrade to the latest version is planned, but other things always seem to take priority. I'll keep the IssueIndexingService in mind for when we upgrade. But for now how would I do this?

I also ran the integrity checker last night and it found 2 of my test issues had errors:

ERROR: WSST-7998 - The current step associated with the workflow entry with id 310968 has an incorrect stepId. (JRA-4539)
ERROR: WSST-8009 - The current step associated with the workflow entry with id 311170 has an incorrect stepId. (JRA-4539)

 

Suggest an answer

Log in or Sign up to answer