Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,361,270
Community Members
 
Community Events
168
Community Groups

Update Space Permissions without Space Admin Part 2

In Part 1 of Updating Space Permissions without Space Admin, we created custom a REST Endpoint in Confluence using ScriptRunner. So now the question is how do we allow our users to call the endpoint? Ultimately this is up to you, there's probably more ways to do this than my convoluted way of using Jira and ScriptRunner for Jira. Here's my solution...

First I create a group for each space that I use to identify users that I want to be able to update permissions. The group doesn't need to be assigned any permissions within Confluence.

I then created an issue type in Jira and associated a workflow with that issue. My issue form asks the following:

  • Confluence Space, Type: Select List (Single)
  • User(s), Type: User Picker (multiple users)
  • Space Permissions, Type: Check boxes
    • Options (You can define whatever options you'd like, I left out any that I only want an Admin to assign)
      • View Space
      • Create/Edit Pages
      • Delete Pages
      • etc....

I have a Jira ScriptRunner job that runs to update the Confluence Space field with the current spaces, seen below:

import com.atlassian.jira.component.ComponentAccessorimport 
com.atlassian.jira.issue.context.GlobalIssueContext
import groovy.json.JsonSlurper 

//Get the a list of space information so we can get all space names
def url = "https://base-url/rest/api/space" 

//Use Postman encrypt your username and password for your Confluence service account with admin permissions.

def basicAuth = "Basic Y234msdlfms3nsnsdffas3=="
def connection = url.toURL().openConnection() 
connection.setRequestProperty("Authorization", basicAuth)connection.connect() 

def json = new JsonSlurper().parseText(connection.getInputStream().getText()) 

def spacesField = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Confluence Space")
def optionsManager = ComponentAccessor.optionsManager
def fieldConfigSchemeManager = ComponentAccessor.fieldConfigSchemeManager
def globalIssueContext = GlobalIssueContext.getInstance()
def configScheme = fieldConfigSchemeManager.getConfigSchemesForField(spacesField[0])[0]
def fieldConfig = configScheme?.oneAndOnlyConfig ?: fieldConfigSchemeManager.getRelevantConfig(globalIssueContext, spacesField[0])
def existingOptions = optionsManager.getOptions(fieldConfig)
def option 

//Loop through the rest call results to get all the space names and add them to the Confluence Space custom field.
json.results.each { space ->             
  
//Check to see if the space name already exists as an option.    
  
option = existingOptions?.find { it.value.equals(space.name as String) }     

  
//If the space name is not already in the list, then add it.    
  
if(!option)    
  
{        
    
optionsManager.createOption(fieldConfig, null, 0, space.name as String)    
  
}     

  
optionsManager = ComponentAccessor.optionsManager    
  
spacesField = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Confluence Space")    
  
fieldConfigSchemeManager = ComponentAccessor.fieldConfigSchemeManager    
  
globalIssueContext = GlobalIssueContext.getInstance()    
configScheme = fieldConfigSchemeManager.getConfigSchemesForField(spacesField[
0])[0]    
  
fieldConfig = configScheme?.oneAndOnlyConfig ?: fieldConfigSchemeManager.getRelevantConfig(globalIssueContext, spacesField[0])    
  
existingOptions = optionsManager.getOptions(fieldConfig)     

  
//Loop through the existing options and disable any option where the space no longer exists (i.e. it has been deleted.)    
  
for (opt in existingOptions)    
  
{        
    
def Boolean exists = false                 
    
json.results.each { spc ->  
          
             
      
if(opt.getValue().equals(spc.name as String))            
      
{                
        
exists = true            
}
        
} 
       
         
  if(!exists)        
    
{            
      
opt.setDisabled(true)        
    
}    
}
}

My workflow has a post function on the create that checks if the user submitting is in the group for the space, then interprets the fields on the form and creates the REST Call and finally makes the call using my service account, as seen below (if not the issue is assigned to me so I can provide the permissions).

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.context.GlobalIssueContext 

import groovy.json.JsonSlurper 
import
 org.apache.log4j.Category  

def Category log = Category.getInstance("com.onresolve.jira.groovy")
log.setLevel(org.apache.log4j.Level.DEBUG) 

//Get the space selected on the issue.
def space = issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Confluence Space")[0]) as String 

//Get the a list of space information so we can associate the space name with the space key.
def url = "https://base-url/rest/api/space" 

//Use Postman encrypt your username and password for your Confluence service account with admin permissions.
def basicAuth = "Basic Ymmdsdsd343sdfmsms=="
def
 connection = url.toURL().openConnection() 

connection.setRequestProperty("Authorization", basicAuth)
connection.connect() 

//Use the selected space to to find the space key from the rest call return.
def json = new JsonSlurper().parseText(connection.getInputStream().getText())
def spaceKey = "spaceKey=" + json.results[json.results.findIndexOf { it.name == space } ].key 

def groupManager = ComponentAccessor.getGroupManager() 

//Check that the user making the request is allowed to update permissions. Notice we concatenate the space key to get the correct owners group for the selected space.
if (groupManager.getUsersInGroup("space-owners-" + json.results[json.results.findIndexOf { it.name == space } ].key.toLowerCase()).contains(issue.getReporter()))
{    
  
//Get the selected permissions from the issue and start building our rest call.    
  
def permissionsField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Space Permissions")    
  
def selectedPermissions = issue.getCustomFieldValue(permissionsField[0])    
  def permissions     
    
  
if (selectedPermissions != null)    
  
{        
    
if (selectedPermissions*.value.contains("View Space"))        
    
{            
      
permissions = "&view=true"        
  }        
    
else        
    
{            
      
permissions = "&view=false"        
    
}         
    
if (selectedPermissions*.value.contains("Create/Edit Pages"))        
    
{            
      
permissions = permissions + "&createEditPage=true"        
    
}        
    
else        
    
{            
      
permissions = permissions + "&createEditPage=false"        
    
}         
    
if (selectedPermissions*.value.contains("Delete Any Page"))        
    
{            
      
permissions = permissions + "&removePage=true"        
    
}        
    
else        
    
{            
      
permissions = permissions + "&removePage=false"        
    
}         
if (selectedPermissions*.value.contains("Create/Edit Blogs"))        
    
{            
permissions = permissions + 
"&editBlog=true"        
    
}        
    
else        
    
{            
      
permissions = permissions + "&editBlog=false"        
}         
    
if (selectedPermissions*.value.contains("Add Attachments"))        
    
{            
      
permissions = permissions + "&createAttachment=true"        
    
}        
    
else        
    
{            
      
permissions = permissions + "&createAttachment=false"        
    
}         
    
if (selectedPermissions*.value.contains("Delete Anyone's Attachments"))        
     
{            
       
permissions = permissions + "&removeAttachment=true"        
     
}        
     
else        
     
{            
       
permissions = permissions + "&removeAttachment=false"        
     
}         
     
if (selectedPermissions*.value.contains("Add Comments"))        
     
{            
       
permissions = permissions + "&comment=true"        
     
}        
     
else        
     
{            
       
permissions = permissions + "&comment=false"        
     
}         
     
if (selectedPermissions*.value.contains("Modify Page Restrictions"))        
     
{            
       
permissions = permissions + "&setPagePermissions=true"        
     
}        
     
else        
{
            
       
permissions = permissions + "&setPagePermissions=false"        
     
}         
     
if (selectedPermissions*.value.contains("Export Space/Pages"))        
     
{            
       
permissions = permissions + "&exportSpace=true"        
     
}        
     
else        
     
{            
permissions = permissions + "&exportSpace=false"        
     
}         
     
if (selectedPermissions*.value.contains("Delete Own"))        
     
{            
       
permissions = permissions + "&removeOwn=true"        
     
}        
     
else        
     
{            
       
permissions = permissions + "&removeOwn=false"        
     
}    
}
    
  
else    
  
{       
  
permissions = "&view=false&removeOwn=false&createEditPage=false&removePage=false&editBlog=false&createAttachment=false&removeAttachment=false&comment=false&setPagePermissions=false&exportSpace=false"       
  
}         

//Get the selected users to apply the permissions to.    
  def userField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("User(s)")    
  
def users = issue.getCustomFieldValue(userField[0])     

//Loop through the users and make the rest call to the rest end point we created in Confluence.
    
  
users.each { user ->                 
url = 
"https://base-url/rest/scriptrunner/latest/custom/updatePermissions?" + spaceKey + "&user=" + user.getUsername() + permissions        
connection = url.toURL().openConnection()
        
    
connection.setRequestProperty("Authorization", basicAuth)        
connection.connect()
                 

    
//Log an error in if the return code is not 200.        
    
if(connection.getResponseCode() != 200) //Shows as error, but works.           
    
{            
      
log.debug("Permissions were not set for user " + user + "!")        
    
}    
  }
}

 

0 comments

Comment

Log in or Sign up to comment
TAGS
Community showcase
Published in Confluence

Watch 4 Confluence apps compete for Best App Demo in September's Appy Hours

Calling all collaborators! Appy Hours on the Atlassian Community is a monthly event where 4 Partner and app vendor presenters go head-to-head with 5-minute demos for the title of Best App Demo. I...

584 views 0 13
Read article

Atlassian Community Events