Setting User Avatar via ScriptRunner

scott_boisvert
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 3, 2020

We recently moved from a Server environment to a Data Center environment for Jira. We kept our Server licenses for some proof of concept work. With Scriptrunner's new LDAP resource I was able to write a script to pull user profile pics from Active Directory and update their profiles in Jira and Confluence. I did this in our Data Center environment and works great. I'm currently running a proof of concept in our server environment with Jira Service Desk. So I thought I would put the script in there as well. However, when running the script in the server environment, the avatars are getting set to the silhouette with a question mark in it instead of the profile picture. When I go to /atlassian/application-data/jira/data/avatars directory, all the images are there and contain the user's profile picture from AD. Checking the users avatar ID after assigning it, points to the correct avatars. I can't find any differences between my Data Center and Server installs other than the fact that they are Data Center and Server. I even tested in my Development Data Center environment by installing a trial of service desk there. Anyone aware of any difference between the two or if there is a permission issue I'm missing? Oh, and if I set to one of the system avatars it works fine.

This is the avatar that is displayed after running the script: image.png

Jira Version: 8.7.1

Script Runner Version: 6.1.0-p5

For reference the code for the script is here:

import com.onresolve.scriptrunner.ldap.LdapUtil
import org.springframework.ldap.core.AttributesMapper
import javax.naming.directory.SearchControls
import javax.naming.directory.Attributes
import com.atlassian.jira.avatar.Avatar
import com.atlassian.jira.avatar.AvatarManager
import com.atlassian.jira.avatar.AvatarService
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.icon.IconType
import com.atlassian.jira.icon.IconOwningObjectId
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.JiraServiceContext
import com.atlassian.jira.bc.JiraServiceContextImpl

import com.atlassian.crowd.manager.directory.DirectoryManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.icon.IconType
import com.atlassian.jira.avatar.AvatarImpl

import com.atlassian.jira.avatar.Avatar.Size

def userManager = ComponentAccessor.getUserManager()
AvatarService avatarService = ComponentAccessor.getAvatarService()

userManager.getAllApplicationUsers().each { user ->

def avatarManager = ComponentAccessor.getAvatarManager()
def avatars = avatarManager.getCustomAvatarsForOwner(IconType.USER_ICON_TYPE, user.name)

avatars.each {avatar ->
if (!avatar.isSystemAvatar() && avatar != null)
{
avatarManager.delete(avatar.id)
}
}

if (user.active)
{
def noPhoto = false
def cnList

if (user.directoryId == 10300)
{
cnList = LdapUtil.withTemplate("GMCC") { template ->
template.search("", "(sAMAccountName=" + user.name + ")", SearchControls.SUBTREE_SCOPE, { attributes ->
if(attributes.get('thumbnailPhoto') != null)
{
noPhoto = true
attributes.get('thumbnailPhoto').get()

}

} as AttributesMapper<byte[]>)
}
}
else if (user.directoryId == 10400)
{
cnList = LdapUtil.withTemplate("IMICO") { template ->
template.search("", "(sAMAccountName=" + user.name + ")", SearchControls.SUBTREE_SCOPE, { attributes ->
if(attributes.get('thumbnailPhoto') != null)
{
noPhoto = true
attributes.get('thumbnailPhoto').get()
}

} as AttributesMapper<byte[]>)
}
}

if (noPhoto)
{
ByteArrayInputStream bis = new ByteArrayInputStream(cnList[0] as byte[])
BufferedImage bImage = ImageIO.read(bis)
ImageIO.write(bImage, "jpg", new File("/data/atlassian/application-data/jira/scripts/data/test.jpg"))

def fileName = "test.jpg"
File file = new File("/data/atlassian/application-data/jira/scripts/data/test.jpg")

def contentType = AvatarManager.PNG_CONTENT_TYPE
IconType iconType = IconType.USER_ICON_TYPE
IconOwningObjectId owner = new IconOwningObjectId(user.name)
BufferedInputStream iStream = new BufferedInputStream(new FileInputStream(file))
Avatar avatar = avatarManager.create(fileName, contentType, iconType, owner, iStream, null)
avatarService.setCustomUserAvatar(user, user, avatar.getId())
}
}
}

2 answers

1 accepted

0 votes
Answer accepted
scott_boisvert
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 5, 2020

I figured this out. I'm not sure I understand why, but setting the IconOwningObjectId with the Jira Administrator account and the remote user on the setCustomUserAvatar call to the Jira Administrator it worked.

Gennady Makhnach April 4, 2023

In this case all avatars will be stored under Administrator profile and user avatars will be 'linked' to them.

It can be a bit confusing for users.

0 votes
Gennady Makhnach April 4, 2023

The original code works for me with one small change:

IconOwningObjectId owner = new IconOwningObjectId(user.name.toLowerCase())


It looks like internally search algorithm for user avatar by user name is case-sensitive but Jira uses User Name in lower case to search. So avatar.owner field should be stored in lower case in database to work correctly.

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
VERSION
8.7.1
TAGS
AUG Leaders

Atlassian Community Events