Adding Space Permissions - Confluence API

confluence
automation
scriptrunner
confluence-api

#1

I am attempting to automate Confluence space creation using REST API calls. So far I have been able to successfully create a space, but since permissions management cannot be done through the REST API, I have elected to do that using the Confluence APIs by setting up a custom REST endpoint in Adaptavist ScriptRunner.

The custom endpoint code works almost perfectly. It accepts a space key and a list of usergroups to be granted access in the space. For each of the groups, a certain list of permissions are granted.

As far as I can tell, I’m interacting with the API correctly by using SpaceManager to get the Space object for the given key, then using the SpacePermission class I’m setting those up, setting the Space’s permissions using the List object, and then using SpaceManager.saveSpace to commit the changes.

This results in the space permissions page looking correct in the browser (all groups have the specified permissions), but when a user attempts to access the space and are in that group, they are not permitted by Confluence to go into the space. The fix for this has been to manually remove the groups from space permissions and then re-add them.

I checked the database before and after this workaround and the only difference in the “spacepermissions” table is that the following columns are empty when the API sets up the permissions: creator, creationdate, lastmodifier, and lastmoddate. These columns are populated when permission is manually granted, so it makes me think that I’m missing something in the process of granting permission through the API.

Any assistance would be greatly appreciated. We’re trying to avoid enabling XML-RPC if at all possible. As a new user I can’t attach the code, but it’s short enough that I think it won’t be too much of an eyesore here.

import com.atlassian.confluence.security.SpacePermission
import com.atlassian.confluence.spaces.Space
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.sal.api.component.ComponentLocator
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.transform.BaseScript
import org.codehaus.jackson.map.ObjectMapper

import javax.servlet.http.HttpServletRequest
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate

String[] permissions = [
    "COMMENT",
    "CREATEATTACHMENT",
    "EDITBLOG",
    "EDITSPACE",
    "EXPORTSPACE",
    "REMOVEATTACHMENT",
    "REMOVEBLOG",
    "REMOVECOMMENT",
    "REMOVEOWNCONTENT",
    "REMOVEPAGE",
    "SETPAGEPERMISSIONS",
    "VIEWSPACE"
]

class Permission {
    String spaceKey
    String[] groups
}

addSpacePermissions(httpMethod: "POST", groups: ["confluence-administrators"]) { MultivaluedMap queryParamas, String body, HttpServletRequest request ->
    def mapper = new ObjectMapper()
    def bean = mapper.readValue(body, Permission.class)
    
    if (bean && bean.spaceKey && bean.groups && bean.groups.size() > 0) {
        SpaceManager spaceManager = (SpaceManager) ComponentLocator.getComponent(SpaceManager)
        
        if (spaceManager == null) {
            String errorMsg = "unable to get Space Manager"
            return Response.serverError().entity([message: errorMsg]).build()
        }
        
        Space space = spaceManager.getSpace(bean.spaceKey)
        
        if (space == null) {
            String errorMsg = "unable to get Space"
            return Response.serverError().entity([message: errorMsg]).build()
        }
        
        List<SpacePermission> spacePermissions = space.getPermissions()
        
        if (spacePermissions == null) {
            String errorMsg = "unable to get Space Permissions"
            return Response.serverError().entity([message: errorMsg]).build()
        }
        
        for (String p : permissions) {
            for (String g : bean.groups) {
                spacePermissions.add(new SpacePermission(p, space, g))
            }
        }
        
        space.setPermissions(spacePermissions)
        spaceManager.saveSpace(space)
        
        return Response.ok().build()
    }

    return Response.noContent().build()
}