Scriptrunner Job auto add group to filters, dashboard and boards as admin.

Zac Boyd
Contributor
October 19, 2023

I am using Jira 9.4.10 
I am want to create a scriptruuner "Job" with a custom script that adds a specific group to be able to admin filters, dashboards and boards every 3 hours. To be begin with I am focusing on Filters. 
I do not want this group to have any higher permissions. hence adding them manually. 

My current code: 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchRequest
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.user.util.UserManager

// Set the name of the group you want to add as an owner
def groupName = "group1"

// Get the SearchRequestService and UserManager components
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def userManager = ComponentAccessor.getComponent(UserManager)

// Get the group by name
def group = userManager.getGroup(groupName)

if (group) {
// Get all filters
def allFilters = SearchRequestService.getOwnedFilters(userManager.getJiraSystemUser())
allFilters.each { filter ->
if (!filter.isGroupOwner(group)) {
// Set the group as an owner of the filter
filter.addOwnerGroup(group)
searchRequestService.update(userManager.getJiraSystemUser(), filter)
log.info("Added group $groupName as an owner of the filter ${filter.name}")
} else {
log.info("Group $groupName is already an owner of the filter ${filter.name}. No changes made.")
}
}
} else {
log.error("Group $groupName not found")
}
This is failing to to read SearchRequestService.getOwnedFilters(userManager.getJiraSystemUser()) as a method, I am new to the dev world and have walk through the API documentation and believe i am using the right class. Any help would be appreciated !

1 answer

0 votes
Peter-Dave Sheehan
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.
October 19, 2023

What filters are you hoping to receive with that line that's failing?

There are a few things wrong with it, but I'm not sure what to suggest since I don't understand what it is trying to do.

1) you've defined an instance of the SearchRequestService class using the variable searchRequestService (notice the lowercase s). Class names are Capitalized, variables/instances of a class are not (by convention). So we need to start by using the lowercase version.

2) The getOwnedFilters() only accepts a ApplicationUser object. You can't search for filters owned by a group because groups can't own filters. Filters are owned by users but can be shared (with edit permissions) to a group. 

3) There is no such method as getJiraSysmteUser() in the UserManager class. So I'm not clear which user you are trying to retrieve.

You might need to rethink your script based on what your actual goal is (change the owner or grant the group edit permissions).

Zac Boyd
Contributor
October 19, 2023

Thanks for the help! @Peter-Dave Sheehan 
Basically all filters created by users I want this group to be able to edit them, to support like a first level service desk. 
I was trying to getOwnedFilters that do not already have that group added to then add the group. Not sure that it was the best way to go about it.

Peter-Dave Sheehan
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.
October 19, 2023

Unfortunately, the only way I can think of, is to iterate over ALL of your filters, identify if the group has Edit permission, and if not, add it.

That will be increasingly wasteful as you create more and more filters.

The only option to find filters not shared to the group is to use a SQL query direct in the database. 

Then you can use groovy to iterate over those filters and add the edit permission.

Here is a SQL query to get you the filters that are not yet shared:

Select s.id
From searchrequest s
Where
s.ID Not In (
Select p.entityid
From sharepermissions p
Where
p.entitytype = 'SearchRequest' And
p.sharetype = 'group' And
p.PARAM1 = 'group1'
)

 

I ended up putting together a full script that should do what you are looking for:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchRequest
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.sharing.SharePermissionImpl
import com.atlassian.jira.sharing.SharedEntity
import com.atlassian.jira.sharing.rights.ShareRights
import com.atlassian.jira.sharing.type.ShareType
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.user.util.UserManager
import com.onresolve.scriptrunner.db.DatabaseUtil
import com.atlassian.jira.bc.JiraServiceContextImpl

// Set the name of the group you want to add as an owner
def groupName = "group1"

// Get the SearchRequestService and UserManager components
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def userManager = ComponentAccessor.getComponent(UserManager)
//get an admin use that has permissions to edit all filter permissions
def adminUser = userManager.getUserByName('admin')
def serviceContext = new JiraServiceContextImpl(adminUser)

//this is the generic permission object we'll add to all filters
def perm = new SharePermissionImpl(ShareType.Name.GROUP, groupName, "", ShareRights.VIEW_EDIT)

def sqlQuery = """
Select
s.id
From
searchrequest s
Where
s.ID Not In (Select
p.entityid
From
sharepermissions p
Where
p.entitytype = 'SearchRequest' And
p.sharetype = 'group' And
p.PARAM1 = :groupName)"""

//query the local jira db (an entry must exist under scriptrunner> resources) for all filters that are not already shared with groupName
DatabaseUtil.withSql('local_jira') { sql ->
sql.rows(sqlQuery, [groupName: groupName])
}.each { row ->
def filter = searchRequestService.getFilter(serviceContext, row.id as Long)
log.info "Adding $groupName to $filter.name ($filter.id)"
def existingPermissions = filter.permissions

def permSet = existingPermissions.permissionSet as List
//add the generic permission to the list of existing permissions
permSet << perm
filter.permissions = new SharedEntity.SharePermissions(permSet as Set)

//save the filter with the updated permissions
searchRequestService.validateFilterForUpdate(serviceContext, filter)
searchRequestService.updateFilter(serviceContext, filter)
}
Like # people like this
Zac Boyd
Contributor
October 22, 2023

So i have to avoid using SQL to search the database. 
Like you've said that its the only way to get it to work on as a "Job"
I've just had a look at "Listeners" and found the event for FilterCreated ( Wasn't aware of this option) rather then validating against database values do you think just adding the role on event FilterCreated would be much simpler ? I'm just drafting up some code with how i think it'll work. 

Like Judah likes this
Peter-Dave Sheehan
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.
October 23, 2023

Yeah, that's a good idea. Didn't think/know about this event.

That definitely seems the way to go. 

I can imagine there is a possibility of some concurrency issues though. If a user creates a filter, then the listener adds the group, meanwhile, the user is also trying to adjust the permissions immediately, I suppose there is a chance that the user's UI will not yet know about the permissions your listener has granted and the user might overwrite the permissions.

But maybe that's a non-issue.

You will also have the possibility that the user decides to remove the group after the fact. 

Like Judah likes this
Akhila Gade January 6, 2024

Hi @Peter-Dave Sheehan 

 

I have a similar situation at hand. I have the id's of the filters shared with "group-A". Now i want to share the filters with "group-B" as well.

 

Could this code be used for that as well? If not, can you help me with a code to achieve the above?

 

Thanks,

Akhila 

Peter-Dave Sheehan
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.
January 8, 2024

Yes, that code can be adapted to iterate over a known list of filter ids instead of getting the ids from the database.

Here is what that might look like:

import com.atlassian.jira.bc.JiraServiceContextImpl
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.sharing.SharePermissionImpl
import com.atlassian.jira.sharing.SharedEntity
import com.atlassian.jira.sharing.rights.ShareRights
import com.atlassian.jira.sharing.type.ShareType
import com.atlassian.jira.user.util.UserManager

// Set the name of the group you want to add as an owner
def groupName = "group-B"

// Get the SearchRequestService and UserManager components
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def userManager = ComponentAccessor.getComponent(UserManager)
//get an admin use that has permissions to edit all filter permissions
def adminUser = userManager.getUserByName('admin')
def serviceContext = new JiraServiceContextImpl(adminUser)

//this is the generic permission object we'll add to all filters
def perm = new SharePermissionImpl(ShareType.Name.GROUP, groupName, "", ShareRights.VIEW_EDIT)

//specify the list of filters that need to be modified
List<Long> filterIdList = [12345, 23456, ]

//iterate over all the filters and adjust permissions
filterIdList.each { id ->
def filter = searchRequestService.getFilter(serviceContext, id)
log.info "Adding $groupName to $filter.name ($filter.id)"
def existingPermissions = filter.permissions

def permSet = existingPermissions.permissionSet as List
//add the generic permission to the list of existing permissions
permSet << perm
filter.permissions = new SharedEntity.SharePermissions(permSet as Set)

//save the filter with the updated permissions
searchRequestService.validateFilterForUpdate(serviceContext, filter)
searchRequestService.updateFilter(serviceContext, filter)
}

Suggest an answer

Log in or Sign up to answer