You can easily remove all permissions from a Confluence DC Space, or a Confluence Cloud Space.  Confluence Server, though? You’re out of luck.

Imagine you migrated from Confluence Cloud to Confluence Server, and you wanted to remove all permissions on a Space (except  for maybe “View Space”).  That’s a whole lot of manually clicking, unless you script it.  You’re going to need ScriptRunner for this.

The script below takes two inputs: a Space key, and a username.  It needs the username of someone on the Space with Admin access, because Confluence will not let you remove EVERYONE  with admin access from the Space.

Someone gets left behind.

 

Okay so it takes those two pieces of information as variables.  It then makes use of two arrays. The first array is a prescribed selection of the permissions you’d like removed from the Space. Want to let everyone keep the View Space permission type? Take it out of the List!
The second array is generated by the script. It’s a list of every username and group name with some kind of permission on the Space.

We then nest two loops, and iterate through the permission types and usernames.  For each permission type,

Overview

It’s possible to connect to a Jira instance using Python, and it’s possible to connect to AWS Comprehend using Python. Therefor, it is possible to marry the two, and use Python to assess the sentiment of Jira issues. There are two caveats when it comes to using this script:

  1. The script assumes you can authenticate against Jira with Basic Web Authentication. If your organization uses Single Sign On, this script would need to be amended. 
  2. The script assumes you’re working with Jira Server or Datacenter.  If you’re using Jira Cloud the approach would be different, but I’m planning to do a post about that in the near future.

The authentication method below is not mine. I have linked to the Stack Overflow page where I found it, in the script comments.

 

The Script

The script starts with three imports. We need the Jira library, logging, and the AWS library (boto3).  You’ll likely need to a PIP install of Jira and boto3, if you’ve not used them before.

After the imports we’re defining client, which we use to interact with the AWS API.  Remember to change your region to whichever region is appropriate for you, in addition

As part of my grad school course work, I had half a dozen XML files with content that needed to be analyzed for sentiment.   AWS Comprehend is a service that analyzes text in a number of ways, and one of those is sentiment analysis.

My options were to either cut and paste the content of 400 comments from these XML files, or come up with a programmatic solution.  Naturally, I chose the latter.

The XML file is formatted like so:

 

         <posts>
          <post id="123456">
            <parent>0</parent>
            <userid>user id</userid>
            <created>timestamp</created>
            <modified>timestamp</modified>
            <mailed>1</mailed>
            <subject>Post title</subject>
            <message> Message content </message> 

 

What I needed to get at was the message element of each post, as well as the post id.

The script imports BeautifulSoup to work with the XML, and boto3, to work with AWS.    We next define a string buffer, because we need to store the results of the analysis somehow.

Next we define the client, which tells AWS everything it needs to know.  Tell it the service you’re after, the AWS region, and the tokens you’d use to authenticate against AWS.

After that we provide a list of XML files that the script needs to parse, and tell it to

I found myself needing to examine issues that came through our Jira Service Desk workflow, to determine if they had a form attached. If they didn’t have a form attached, i.e. someone created the issue manually instead of through the Service Desk Portal, the workflow would be instructed to handle them in a certain way.

This turned out to be surprisingly difficult.  There’s no easily accessed attribute associated with issues in Jira that indicates whether or not they have a form attached.

In the end, I determined that it was possible to examine issues in this way by applying some JQL to them.

 import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.bc.issue.search.SearchService

def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def issueManager = ComponentAccessor.getIssueManager()
def searchService = ComponentLocator.getComponent(SearchService)
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def issue = issueManager.getIssueObject("<issue key>")
//Define an issue against which the script will be run

def queryParser = ComponentAccessor.getComponent(JqlQueryParser)
def query = queryParser.parseQuery('issueFormsVersion > 1 and key = '+ issue.key)
//Define the query parameters

def search = searchService.search(user, query, PagerFilter.getUnlimitedFilter())
//This gives us a list of issues that match the query

if(search.results.size() > 0){
    //Do something here
    //If any results were found, it means that the issue had a form attached

Overview

I found myself with an interesting Jira problem today.  We had a dashboard that wasn’t showing all issues relevant to the JQL query in the filter.   The issues were fully present in the system, but would only appear if we went in after creation and tweaked them in some way.
Essentially we had issues that weren’t being picked up by the filter because the system didn’t see them as “complete”.

Here’s the sanitized JQL:

 project = <project> AND status = Queued AND "<Custom Field>" = "<value>" 

It was picking up some of the issues, remember. And the issues were all created in the same way: they came in through the Service Desk as Service Requests. So the JQL wasn’t the issue.

Trying Different Solutions

I already had a listener running as part of the process, so I tried adding an issueUpdate statement to it:

 issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false) 

This did not resolve the issue.   I next tried updating the issue summary to be itself as part of the Workflow Transition process:

 issue.setSummary(issue.summary + " - " + issue.reporter.displayName) 

This also did not resolve the issue.

Resolving the Issue

In the end I solved the issue by introducing a re-index

Introduction

Once upon a time I spent a week writing a script to automate some functionality for Jira.  The script was supposed to assign issues based on certain criteria, and also update a custom field that contained the name of the team that was currently responsible for the ticket.

At the end of the week I had the script working according to the specifications.   We tested it on Friday afternoon, and all was well.
On Monday morning the project manager sent me an email, notifying me that the script now had to work a completely different way.  It also had to be finished by the end of that day, as Tuesday was the day they were using the script as part of a training session.

Updating the Script

The good news was that for the most part, the changes I had to make to the script were reductive. It had to do fewer things.   However, I had initially included the Custom Field update as part of the transition:

    def issueInputParameters = issueService.newIssueInputParameters()
    issueInputParameters.addCustomFieldValue(customFieldID, customFieldValue)
    //The request is for a new workstation, so set Next to Act to Tier 1 - IDIR Services
    issueInputParameters.setSummary(issue.summary + " - " + issue.getReporterUser().displayName)
    //Set 

I have series of ProForma forms that are submitted as issues to the Jira Service Desk.

I needed to run some scripts against these issues after they were created and fast-tracked into a Queued state.  I elected to run a Groovy script as a Listener on Issue Update. The thinking was that because the state of the ticket was being updated from Open to Queued, the Listener would have plenty of material to work with.

The issue that I encountered was that the listener was only detecting some of the issues.  I enabled logging at the outset of the Listener script and told it to record any ticket that was subject to an Issue Updated event.  Some of the issues created by the forms weren’t being detected by this at all. At the same time, some of them were.

The issue was consistent, in that certain forms were never detected by the listener, and certain forms were always detected.  There was no appreciable difference in the form setup or the way the tickets were processed.  The Listener script itself simply examined the Request Type field of each ticket (which is a Jira Core field), and routed the ticket based on

 

During the process of writing a listener for Jira, I found myself encountering a strange error.  The error looked like this:

com.atlassian.servicedesk.api.AuthorizationException: The action performed required a logged in user. Please log in and try again.

This was strange for two reasons. First, I am a Jira administrator with total access to the entire instance. Second, my script had explicitly supplied the logged-in user (myself) as the account under which to run the script.

What gives?

The code I used to supply my own account to the script looks like so:

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

This solution had been more than sufficient previously.   I searched and I searched and I couldn’t find anything related to my issue.  If you search the text of the error, three results are returned, and they’re about REST API permissions. Not applicable here.

In the end I accidentally stumbled on the answer, by trying different solutions for the action I was trying to take.  What I was trying to do was get the Request Type of the issue in question.

The solution was to explicitly provide an account to the script, under which the method could run.   That is, I changed the code to:

I found myself in a situation wherein a ProForma form on the Jira Service Desk contained a custom field.  I needed the contents of that field to dictate which team the resulting issue was assigned to.

The first thing I tried was to add a Groovy script to a transition in the Service Desk Workflow.   If I could tell the script to transition the issue based on the value of a field, the issue should be resolved.

This turned out to not be possible. For some reason, the value of a custom field is not populated from the form to the field until after the ticket “lands”, or finishes moving through the workflow.  It’s not enough to simply trigger the script after the Open/Create transition.   No matter what, the value of the custom field is not available until after all of the initial transitions have finished.  No matter how you try to reference the custom field, the value returned will always be NULL.

This was extremely aggravating, especially when it seems like such a simple solution SHOULD work, and it’s not clear whether the issue lies with your script or with the system.

The solution you’re going to come across

Introduction

Jira Issues can only be transition between states in a manner that resembles the Workflow of the parent project. In other words, before you begin trying to script the transition of a Jira issue, you must understand the workflow and what the available transitions actually are.

Further to that point, there’s more to transitions that simply changing the status of an issue. Some transitions have criteria.  For example, you may want to move an issue from Open to Pending.  In order to do so, you may need to select a Pending State, and add a comment.  How do you account for that in a script?

Using Groovy and ScriptRunner to transition Jira issues is a pretty straightforward process. So too is this process quite simple if you need to include transition criteria.  It’s simple, if you can find a guide on how to do it. As with most of the things I blog about, I couldn’t find instructions for accomplishing this simple task, so I’m writing my own.

Overview

The script we’re going to explore transitions a Jira issue from one state to another, and fills in the criteria required to make the transition a valid one.  As