How do you bulk delete or deactivate users?

This question is in reference to Atlassian Documentation: Add, edit and remove users

How do you bulk delete or deactivate users?

3 answers

1 accepted

0 votes
Accepted answer
Mikael Sandberg Community Champion Mar 09, 2016

There is no option in JIRA to do that, but there are plugins out there that can. User Deactivator for JIRA is one, or you could use the REST API and create your own plugin/script for it.

Hi Mikael

It would be great if you can provide the link for REST API.

In case it helps other searchers, I wrote the following script (as an amalgamation of other people's scripts) to handle this very quickly in the Scriptrunner console.

The goal was for this to be very reproducible, so hopefully it helps out.  The example below is used to delete all users of a certain domain, but you could tweak it to use other search parameters.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.user.search.UserSearchService
import com.atlassian.jira.bc.user.search.UserSearchParams
import com.atlassian.jira.bc.user.UserService
import com.atlassian.jira.user.ApplicationUser

def userSearchService = ComponentAccessor.getComponent(UserSearchService.class);
// The search will be case sensitive, so you may need to do multiple runs. (@abc.com, @ABC.com, etc)
def domainToDelete = "@spam.email"
// The deletion process does not scale well, so play with the number to delete and see what works best. 50-100 has worked well thus far.
// You can test more safely by trying out 1 or 2 users as you confirm your rules.
Integer deletionBatchSize = 50
UserSearchParams userSearchParams = (new UserSearchParams.Builder()).allowEmptyQuery(true).includeActive(true).includeInactive(true).maxResults(deletionBatchSize).build();

def userService = ComponentAccessor.getComponent(UserService)
def asUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

userSearchService.findUsers(domainToDelete, userSearchParams).each{

String jiraUserName = it.getName();

// Confirm 100% that the user we are deleting is actually in the domain to delete by confirming that their
// jira username ends with the domain
// The search params can sometimes find matches based on domainToDelete if portions of the string exist in the userName without this protection
if (jiraUserName.endsWith(domainToDelete)){
final UserService.DeleteUserValidationResult result = userService.validateDeleteUser(asUser, it)
log.error "REMOVAL TEST - $it matched domain"

if (result.isValid()) {
// If you would like to test the script without actually deleting the users found, comment the line below out when you run it.
userService.removeUser(asUser, result)
log.error "REMOVAL SUCCESSFUL - $it"
}
else {
log.error "REMOVAL FAILED - $it " + result.getErrorCollection().errorMessages
}
}
else {
log.error "REMOVAL SKIPPED - " + jiraUserName + " did not match domain: " + domainToDelete + " for removal";
}

}

Patrick, do you think there would be any way to use this script to delete users based on a JQL statement? If so, can you please help! I getting very frustrated deleting/disabling users via the GUI. Thanks in advance!

Parker,

I never found a way to do it with JQL, just the Script Runner  add-on.

After I posted the answer on this thread, I apparently wrote a Script Listener to block spam accounts (Service Desk portal sign-up) from getting created at all. Here you go in case it helps. Originally answered in this post.

  1. After installing go to Admin Cog > Add-Ons > SCRIPTRUNNER category in left panel > Script Listeners
    1. https://yourServiceDesk/plugins/servlet/scriptrunner/admin/listeners
  2. Click Add New Item > Custom Listener
  3. Set Events to monitor UserCreatedEvent
  4. To block a certain domain
    1. import com.atlassian.jira.user.ApplicationUser
      import com.atlassian.crowd.model.user.User
      import com.atlassian.crowd.event.user.UserCreatedEvent
      import com.atlassian.jira.component.ComponentAccessor
      import com.atlassian.jira.bc.user.UserService

      // Catch the UserCreatedEvent and get the User
      def newUserEvent = event as UserCreatedEvent;
      User newUser = newUserEvent.getUser();
      String email = newUser.getEmailAddress();

      // Define the domain you want to block
      String spamDomain = "@spam.xyz";

      if (email.toUpperCase().endsWith(spamDomain.toUpperCase())){

      log.error "SPAMBOT DETECTED! " + email;

      def userService = ComponentAccessor.getComponent(UserService)
      def userManager = ComponentAccessor.getUserManager();

      // Set the user account we want to run delete permissions with
      ApplicationUser runAsUser = userManager.getUserByKey("yourJiraAdminAccount")

      // validate permissions
      final UserService.DeleteUserValidationResult result = userService.validateDeleteUser(runAsUser, email)
      if (result.isValid()) {
      log.error "SPAMBOT REMOVAL VALID - $email"
      userService.removeUser(runAsUser, result)
      log.error "SPAMBOT REMOVAL SUCCESSFUL - $email"
      }
      else
      {
      log.error "REMOVAL INVALID - $email"
      }

      }
  5. To only allow a certain domain
    1. import com.atlassian.jira.user.ApplicationUser
      import com.atlassian.crowd.model.user.User
      import com.atlassian.crowd.event.user.UserCreatedEvent
      import com.atlassian.jira.component.ComponentAccessor
      import com.atlassian.jira.bc.user.UserService

      // Catch the UserCreatedEvent and get the User
      def newUserEvent = event as UserCreatedEvent;
      User newUser = newUserEvent.getUser();
      String email = newUser.getEmailAddress();

      // Define the domain you want to allow
      String allowedDomain = "@safeDomain.com";

      if (!email.toUpperCase().endsWith(allowedDomain.toUpperCase())) {

      log.error "EXTERNAL ATTEMPT DETECTED! " + email;

      def userService = ComponentAccessor.getComponent(UserService)
      def userManager = ComponentAccessor.getUserManager();

      // Set the user account we want to run delete permissions with
      ApplicationUser runAsUser = userManager.getUserByKey("yourJiraAdminAccount")

      // validate permissions
      final UserService.DeleteUserValidationResult result = userService.validateDeleteUser(runAsUser, email)
      if (result.isValid()) {
      log.error "EXTERNAL ATTEMPT REMOVAL VALID - $email"
      userService.removeUser(runAsUser, result)
      log.error "EXTERNAL ATTEMPT REMOVAL SUCCESSFUL - $email"
      }
      else
      {
      log.error "EXTERNAL ATTEMPT REMOVAL INVALID - $email"
      }

      }

Thanks for the help Patrick! Much appreciated.

Patrick, would there be a way to manually add users to delete?
Where you say

def domainToDelete = "@spam.email"

instead I want to delete the account parker@atlassian.xyz. How does the script change in order me to be able to put individuals that need to be deleted?

 

Are you thinking of doing something like pasting in a list of email addresses for the accounts you want to delete?

@Parker Van Dyk - If they are inactive users,  you might be best served by this script, which you can set up to auto-delete users that are inactive for X days.

Otherwise, something like the following will do it. If you've found this helpful, feel free to thumb my original response up so that others are more likely to see it.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.user.search.UserSearchService
import com.atlassian.jira.bc.user.UserService
import com.atlassian.jira.user.ApplicationUser

def userService = ComponentAccessor.getComponent(UserService)
def userSearchService = ComponentAccessor.getComponent(UserSearchService)
def asUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def addressesToDelete = ["emailABC@faker.com","GetRidOfMe@email.com","etc@etc.com"]
for (def i = 0; i < addressesToDelete.size(); i++) {
def user = userSearchService.findUsersByEmail(addressesToDelete[i])
if (user){
ApplicationUser thisUser = user[0]
log.error "The username is: " + thisUser.getName()
final UserService.DeleteUserValidationResult result = userService.validateDeleteUser(asUser, thisUser)

if (result.isValid()) {
// Uncomment the line ncommentbelow to actually delete the account. It is commented for testing.
//userService.removeUser(asUser, result)
log.error "REMOVAL SUCCESSFUL - $thisUser"
}
else {
log.error "REMOVAL FAILED - $thisUser " + result.getErrorCollection().errorMessages
}
}
else
{
log.error "No user account found for: "+ addressesToDelete[i]
}
}

  

@Patrick SavagoI am actually wanting to paste a list of email addresses of users that I want to strip out of all groups/licensing and deactivate. Since we are using cloud, deleting the users would have hurt is more than help. Any suggestions?

Thanks in advance!

@Parker Van Dyk - Gotcha. That starts to get too far outside the original scope of this question. The logic of utilizing the list, looping, logging, etc in the last comment would all still be valid, but instead of doing a delete trial and the .removeUser you would want some logic that deactivated the user. I haven't done that myself before, but I'm sure there's a function to do it that you could substitute into the script.

If you don't see an existing forum post or document that has a code snip of disabling a user account, pop it in as a new question on the community.

 final UserService.DeleteUserValidationResult result = userService.validateDeleteUser(asUser, thisUser) 

if (result.isValid()) {
// Uncomment the line ncommentbelow to actually delete the account. It is commented for testing.
//userService.removeUser(asUser, result)
Like 1 person likes this

Thanks for the info @Patrick Savago I'll keep searching for that function! Thanks for all your help.

removeUser and updateUser with the deactivate parameter can be used. They are part of the JIRA Command Line Interface (CLI).

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Oct 09, 2018 in Jira Core

How to manage many similar workflows?

I have multiple projects that use variations of the same base workflow. The variations depend on the requirements of the project or issue type. The variations mostly come in the form of new statuses ...

240 views 6 0
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you