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:
I have a Jira ScriptRunner job that runs to update the Confluence Space field with the current spaces, seen below:
importcom.atlassian.jira.component.ComponentAccessorimport
com.atlassian.jira.issue.context.GlobalIssueContextimportgroovy.json.JsonSlurper
//Get the a list of space information so we can get all space namesdefurl ="https://base-url/rest/api/space"
//Use Postman encrypt your username and password for your Confluence service account with admin permissions.defbasicAuth ="Basic Y234msdlfms3nsnsdffas3=="defconnection = url.toURL().openConnection()connection.setRequestProperty("Authorization", basicAuth)connection.connect()defjson =newJsonSlurper().parseText(connection.getInputStream().getText())defspacesField = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Confluence Space")defoptionsManager = ComponentAccessor.optionsManagerdeffieldConfigSchemeManager = ComponentAccessor.fieldConfigSchemeManagerdefglobalIssueContext = GlobalIssueContext.getInstance()defconfigScheme = fieldConfigSchemeManager.getConfigSchemesForField(spacesField[0])[0]deffieldConfig = configScheme?.oneAndOnlyConfig ?: fieldConfigSchemeManager.getRelevantConfig(globalIssueContext, spacesField[0])defexistingOptions = optionsManager.getOptions(fieldConfig)defoption//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.nameasString) }
//If the space name is not already in the list, then add it.
if(!option)
{
optionsManager.createOption(fieldConfig,null,0, space.nameasString)
}
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 (optinexistingOptions)
{
defBoolean exists = false
json.results.each{ spc ->
if(opt.getValue().equals(spc.nameasString))
{
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).
importcom.atlassian.jira.component.ComponentAccessorimportcom.atlassian.jira.issue.context.GlobalIssueContextimportgroovy.json.JsonSlurper
importorg.apache.log4j.CategorydefCategory log = Category.getInstance("com.onresolve.jira.groovy")log.setLevel(org.apache.log4j.Level.DEBUG)//Get the space selected on the issue.defspace = issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Confluence Space")[0])asString//Get the a list of space information so we can associate the space name with the space key.defurl ="https://base-url/rest/api/space"//Use Postman encrypt your username and password for your Confluence service account with admin permissions.defbasicAuth ="Basic Ymmdsdsd343sdfmsms=="
defconnection = url.toURL().openConnection()connection.setRequestProperty("Authorization", basicAuth)connection.connect()//Use the selected space to to find the space key from the rest call return.defjson =newJsonSlurper().parseText(connection.getInputStream().getText())defspaceKey ="spaceKey="+ json.results[json.results.findIndexOf{ it.name == space } ].keydefgroupManager = 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.
defpermissionsField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Space Permissions")
defselectedPermissions = issue.getCustomFieldValue(permissionsField[0])defpermissions
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.defuserField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("User(s)")
defusers = 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 +"!")
}}}
scott_boisvert
Senior Systems Integration Engineer
Sierra Space
Thornton, CO
6 accepted answers
0 comments