What is the best way to sync user groups to Service Desk Organizations?

Eric Collins March 29, 2018

Having a way to sync groups of users to specific Service Desk Organizations would be a lifesaver. Any help or advice?

4 answers

1 accepted

2 votes
Answer accepted
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.
March 29, 2018

Hi Eric, 

So, without knowing any details, I am thinking of a Service that will run every <time> and will do the sync, or even a script that you will tun it from the script console. 

The script that will perform the sync will look like 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.servicedesk.api.ServiceDeskManager
import com.atlassian.servicedesk.api.organization.CustomerOrganization
import com.atlassian.servicedesk.api.organization.OrganizationService
import com.atlassian.servicedesk.api.util.paging.SimplePagedRequest
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

@WithPlugin("com.atlassian.servicedesk")

def serviceDeskManager = ComponentAccessor.getOSGiComponentInstanceOfType(ServiceDeskManager)
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)

def adminUser = ComponentAccessor.userManager.getUserByKey("admin")
def project = ComponentAccessor.projectManager.getProjectByCurrentKey("SDP")

def serviceDeskProjectResult = serviceDeskManager.getServiceDeskForProject(project)
if (serviceDeskProjectResult.isLeft()) {
log.debug serviceDeskProjectResult.left().get()
return
}

def serviceDeskId = serviceDeskProjectResult.right().get().id

def organizationQuery = organisationService.newOrganizationsQueryBuilder()
.serviceDeskId(serviceDeskId)
.pagedRequest(new SimplePagedRequest(0, 50))
.build()

def organizationsResult = organisationService.getOrganizations(adminUser, organizationQuery)
if (organizationsResult.isLeft()) {
log.debug organizationsResult.left().get()
return
}

def organization = organizationsResult.right().get().results.findByName("Jira Users")
syncGroupUsersToOrganization(organization, "jira-users")


void syncGroupUsersToOrganization(CustomerOrganization organization, String groupName ) {
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)

def adminUser = ComponentAccessor.userManager.getUserByKey("admin")
def usersInOrganization = organisationService
.newUsersInOrganizationQuery()
.customerOrganization(organization)
.pagedRequest(new SimplePagedRequest(0, 50))
.build()

def currentUsersInOrganizationResult = organisationService.getUsersInOrganization(adminUser, usersInOrganization)
if (currentUsersInOrganizationResult.isLeft()) {
currentUsersInOrganizationResult.left().get()
return
}

def currentUsersInOrganization = currentUsersInOrganizationResult.right().get().results
def usersInGroup = ComponentAccessor.groupManager.getUsersInGroup(groupName)

def usersToRemove = currentUsersInOrganization - usersInGroup
def usersToAdd = usersInGroup - currentUsersInOrganization

def usersToAddInOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToAdd?.toSet()).build()
def usersToRemoveFromOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToRemove?.toSet()).build()

organisationService.addUsersToOrganization(adminUser, usersToAddInOrganizationUpdateParameters) // add users that are in the group and not in the organization
organisationService.removeUsersFromOrganization(adminUser, usersToRemoveFromOrganizationUpdateParameters) //remove users that are no longer in that group
}

Keep in mind that this is not properly tested, and given the fact that people in an organisation may have access to issues with confidential information, you will have to make sure that the expected users are in the expected organisations.

One more thing, to keep in mind is that every project has its own organisations. 

Please let me know if you have any questions. 

Regards, Thanos

Eric Collins March 29, 2018

Thank you so much for helping. Copying what you have (changing just the username and project) I am getting the following error:

2018-03-29 19:59:03,698 WARN [common.UserScriptEndpoint]: Script console script failed: groovy.lang.MissingMethodException: No signature of method: com.atlassian.servicedesk.internal.feature.organization.api.OrganizationsQueryImpl$Builder.serviceDeskId() is applicable for argument types: (com.atlassian.servicedesk.internal.feature.servicedesk.ServiceDeskImpl) values: [ServiceDeskImpl{serviceDeskId=1, projectId=10001, projectName=Release Management, accessConfig=AccessConfig{publicSignUp=false, openAccess=true}, createdByUserKey=some(egcolli), createdDate=some(2018-03-20 17:33:01.671), createdWithEmptyProject=some(true), createdAtVersion=some(3.11.1-REL-0014), legacyCommentTransitionDisabled=true}] Possible solutions: serviceDeskId(java.lang.Integer) at Script57.run(Script57.groovy:24)

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.
March 30, 2018

Hi Eric,

can I ask you in which version of Service Desk you are ?

Eric Collins March 30, 2018

Of course, for SD we are using 3.6.2 and JIRA 7.4.2

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.
March 30, 2018

Hey Eric, 

That is weird I just ran the script with the same versions as you and It works fine. 

I also ran it against service desk version 3.11.1 

Can you please make sure that you copied the script correctly ? Especially the lines 

def serviceDeskId = serviceDeskProjectResult.right().get().id

def organizationQuery = organisationService.newOrganizationsQueryBuilder()
.serviceDeskId(serviceDeskId)
.pagedRequest(new SimplePagedRequest(0, 50))
.build()

Also if you pasted this into the script console and you get some error indications, is it safe to ignore them probably are because of the static type checking. Just run it and then check the application logs if any "real"

Thanks, Thanos

Eric Collins March 30, 2018

Awesome. It works now.

Baris Kuzu October 1, 2018

Hello @Thanos Batagiannis [Adaptavist],

using the code above I get the follow error. Would you please give me a hint what I am doing wrong?

JIRA Service Desk 3.11.2

JIRA Software 7.8.2

 

Kind regards 

Baris

 

Error-scriptrunner.jpg

Tony Mackin February 27, 2019

Hi @Thanos Batagiannis _Adaptavist_  

The script above works great for groups/orgs less than 50 people. 

 

Is there a way to modify the pageRequest lines to support over 50 people,  like upto 1000?

Deleted user August 13, 2019

Hi,

we used this script successfully until we updated to Jira  8.2.0 (SD: 4.2.0).

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.servicedesk.api.ServiceDeskManager
import com.atlassian.servicedesk.api.organization.CustomerOrganization
import com.atlassian.servicedesk.api.organization.OrganizationService
import com.atlassian.servicedesk.api.util.paging.SimplePagedRequest
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

@WithPlugin("com.atlassian.servicedesk")

def serviceDeskManager = ComponentAccessor.getOSGiComponentInstanceOfType(ServiceDeskManager)
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)

def adminUser = ComponentAccessor.userManager.getUserByKey("User")
def project = ComponentAccessor.projectManager.getProjectByCurrentKey("KEY")

def serviceDeskProjectResult = serviceDeskManager.getServiceDeskForProject(project)
if (serviceDeskProjectResult.isLeft()) {
log.debug serviceDeskProjectResult.left().get()
return
}

def serviceDeskId = serviceDeskProjectResult.right().get().id

def organizationQuery = organisationService.newOrganizationsQueryBuilder()
.serviceDeskId(serviceDeskId)
.pagedRequest(new SimplePagedRequest(0, 50))
.build()

def organizationsResult = organisationService.getOrganizations(adminUser, organizationQuery)
if (organizationsResult.isLeft()) {
log.debug organizationsResult.left().get()
return
}

def organizationAll = organizationsResult.right().get().results.findByName("Organization_Z")
syncGroupUsersToOrganization(organizationAll, "Group_Z")

def organizationH41 = organizationsResult.right().get().results.findByName("Organization_A")
syncGroupUsersToOrganization(organizationH41, "Group_A")

def organizationT38 = organizationsResult.right().get().results.findByName("Organization_B")
syncGroupUsersToOrganization(organizationT38, "Group_B")

def organizationL254 = organizationsResult.right().get().results.findByName("Organization_C")
syncGroupUsersToOrganization(organizationL254, "Group_C")

void syncGroupUsersToOrganization(CustomerOrganization organization, String groupName ) {
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)

def adminUser = ComponentAccessor.userManager.getUserByKey("User")
def usersInOrganization = organisationService
.newUsersInOrganizationQuery()
.customerOrganization(organization)
.pagedRequest(new SimplePagedRequest(0, 50))
.build()

def currentUsersInOrganizationResult = organisationService.getUsersInOrganization(adminUser, usersInOrganization)
if (currentUsersInOrganizationResult.isLeft()) {
currentUsersInOrganizationResult.left().get()
return
}

def currentUsersInOrganization = currentUsersInOrganizationResult.right().get().results
def usersInGroup = ComponentAccessor.groupManager.getUsersInGroup(groupName)

def usersToRemove = currentUsersInOrganization - usersInGroup
def usersToAdd = usersInGroup - currentUsersInOrganization

def usersToAddInOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToAdd?.toSet()).build()
def usersToRemoveFromOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToRemove?.toSet()).build()

organisationService.addUsersToOrganization(adminUser, usersToAddInOrganizationUpdateParameters) // add users that are in the group and not in the organization
organisationService.removeUsersFromOrganization(adminUser, usersToRemoveFromOrganizationUpdateParameters) //remove users that are no longer in that group
}

Now we are getting this error: 

 

groovy.lang.MissingMethodException: No signature of method: com.atlassian.servicedesk.internal.feature.servicedesk.ServiceDeskImpl.isLeft() is applicable for argument types: () values: [] Possible solutions: inspect(), inject(groovy.lang.Closure), inject(java.lang.Object, groovy.lang.Closure), sleep(long), sleep(long, groovy.lang.Closure), split(groovy.lang.Closure) at Script35.run(Script35.groovy:17)

No signature of method: com.atlassian.servicedesk.internal.feature.servicedesk.ServiceDeskImpl.isLeft()

 

Does someone have an Idea how solve this issue?

Like Deleted user likes this
Tony Mackin April 29, 2020

We upgraded to  JSD 4.5.4 / Jira Core 8.5.4  and get same error message.     

Anyone have an updated version that works on Jira 8.x /  JSD 4.x?

1 vote
Nhat Tu
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.
December 4, 2018

Hi @Eric Collins @Baris Kuzu,

If you still have this error. See my code below can help you  

Error-scriptrunner (1).jpg

This is my solution below. Also if you pasted this into the script console and get some error indications, is it safe to ignore them probably are because of the static type checking. Just run it and then check the application logs if any "real"

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.servicedesk.api.ServiceDeskManager
import com.atlassian.servicedesk.api.organization.CustomerOrganization
import com.atlassian.servicedesk.api.organization.OrganizationService
import com.atlassian.servicedesk.api.util.paging.SimplePagedRequest
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

@WithPlugin("com.atlassian.servicedesk")
def serviceDeskManager = ComponentAccessor.getOSGiComponentInstanceOfType(ServiceDeskManager)
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)
//get your Project Key and your User Key
//my project key=IP and user=admin
def adminUser = ComponentAccessor.userManager.getUserByKey("admin")
def project = ComponentAccessor.projectManager.getProjectByCurrentKey("IP")

def serviceDeskProjectResult = serviceDeskManager.getServiceDeskForProject(project)
if (serviceDeskProjectResult.isLeft()) {
log.debug serviceDeskProjectResult.left().get()
return
}
//note: service desk id != project id
def serviceDeskId = serviceDeskProjectResult.right().get().id
def organizationQuery = organisationService.newOrganizationsQueryBuilder()
.serviceDeskId(serviceDeskId)
.pagedRequest(new SimplePagedRequest(050))
.build()
def organizationsResult = organisationService.getOrganizations(adminUser, organizationQuery)
if (organizationsResult.isLeft()) {
log.debug organizationsResult.left().get()
return
}
//put your organization ex:VAA
def organization = organizationsResult.right().get().results.findByName("VAA")
//sync your group ex:HR Dep’t to organization VAA
syncGroupUsersToOrganization(organization, "HR Dep’t")
void syncGroupUsersToOrganization(CustomerOrganization organization, String groupName ) {
def organisationService = ComponentAccessor.getOSGiComponentInstanceOfType(OrganizationService)
def adminUser = ComponentAccessor.userManager.getUserByKey("admin")
def usersInOrganization = organisationService
.newUsersInOrganizationQuery()
.customerOrganization(organization)
.pagedRequest(new SimplePagedRequest(050))
.build()
def currentUsersInOrganizationResult = organisationService.getUsersInOrganization(adminUser, usersInOrganization)
if (currentUsersInOrganizationResult.isLeft()) {
currentUsersInOrganizationResult.left().get()
return
}
def currentUsersInOrganization = currentUsersInOrganizationResult.right().get().results
def usersInGroup = ComponentAccessor.groupManager.getUsersInGroup(groupName)
def usersToRemove = currentUsersInOrganization - usersInGroup
def usersToAdd = usersInGroup - currentUsersInOrganization
def usersToAddInOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToAdd?.toSet()).build()
def usersToRemoveFromOrganizationUpdateParameters = organisationService.newUsersOrganizationUpdateParametersBuilder().organization(organization).users(usersToRemove?.toSet()).build()
organisationService.addUsersToOrganization(adminUser, usersToAddInOrganizationUpdateParameters) // add users that are in the group and not in the organization
organisationService.removeUsersFromOrganization(adminUser, usersToRemoveFromOrganizationUpdateParameters) //remove users that are no longer in that group
}

 

0 votes
Dzmitry Hryb _Deviniti_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
November 7, 2018

Hi @Eric Collins @Baris Kuzu,

That's right, syncing Jira user groups with Jira Service Desk Organizations has not been available out-of-the-box, and there's been no workaround other than scripting as provided by @Thanos Batagiannis _Adaptavist_... until we at Deviniti added Organizations and Groups Sync as an admin feature to Extension for Jira Service Desk. Now it's just a simple configuration with two possibilities: you either create new Organizations straight from the respective user groups, or assign them to existing ones (multiple groups to one Org as well). Both options are synced by a single CRON expression. Learn more by reading this article if you're interested, and feel free to ask any questions.

Cheers,

Dzmitry

Johan Eckerstrom - {Eficode} September 17, 2020

Hi , 

Will you any time add a function to delete the organizations from the project also?

Cheers 

Johan

Katarzyna
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 17, 2020

Hi Johan,

We have no plans to develop this functionality. But please submit a request via our customer portal. We collect any feedback from our users, so maybe in the future we'll add this option.

Kate

0 votes
Baris Kuzu September 12, 2018

 

 

 

amit anand May 22, 2020

 

I am getting below error on this code.


def serviceDeskProjectResult = serviceDeskManager.getServiceDeskForProject(project)
if (serviceDeskProjectResult.isLeft()) {
log.debug serviceDeskProjectResult.left().get()
return
}
//note: service desk id != project id

 

error1.PNG

Anyone have updated code then please share.

I am using Jira Software - 8.5.0 and JIRA Service Desk Application - 4.5.0

Thanks

Amit Anand

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events