Confluence - Scriptrunner: How could I automatically remove restrictions of a page e.g. by a Job?

Patrick December 4, 2020

Hello, actually we want to reveal some documents at a given time. The documents already exist, but viewable (as well as editable) only for some specific users.

The idea is to reveal the documents at a given point of time e.g. regularly every saturday at 08:00 am. 

We've licensed Scriptrunner Confluence app already for other features, but it seems that the "Jobs" feature with "CQL escalation service" could be a good solution:

  • CQL query pages with a specific label
  • Set up a cron to the required point in time
  • And add an inline script to add permission/remove restriction

But it turns out, that the script is the problem here.

I've started to hack something, but without success.

The naiv idea would be to use the script below as a starting point, get the parent of the actual content page and add the parents permission to the actual content: 

 

import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.it.content.security

hits.each { content ->
log.warn "Removed the restriction from: ${content.title}"

// how to get the parent content permission? As it has no restrictions set.
// how to set that content permission to the content
// e.g. content.addPermission(parent permission)
}

 

Is it even possible to remove a restriction with a Job and if yes, could someone give me some hints, how to solve that? 

 

Thank you very much in advance!

1 answer

1 accepted

0 votes
Answer accepted
Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 4, 2020

Hi @Patrick 

Short answer: Yes! 

I know ScriptRunner quite a bit and almost everything is possible :-) 

Can you give me some more information, then I can test on my own and share the script. 

  • Do you want the delete ALL the restrictions of ANY page in a space?
  • Do you want the delete ALL the restrictions of a specific page in a space?
  • Do you want the delete only some of the restrictions of some pages?

Thanks for the answers.

Looking forward to help you.

Regards, Dominic

Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 4, 2020

Okay, I misread something, sorry. You want to do that with CQL. 

What I did:

I made a Script in the Script Editor:

package confluence

import com.atlassian.sal.api.component.ComponentLocator;
import com.atlassian.confluence.pages.PageManager;
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.confluence.pages.Page
import com.atlassian.confluence.core.ContentPermissionManager
import com.atlassian.confluence.security.ContentPermission

import static com.atlassian.confluence.security.ContentPermission.EDIT_PERMISSION
import static com.atlassian.confluence.security.ContentPermission.VIEW_PERMISSION

class RestrictionHandler {

def deleteAllViewPermissionOnPage(Long pageId, String permissionType){
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

deletePermission(pageId, permissionType)
}

def deleteAllEditPermissionOnPage(Long pageId, String permissionType){
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

deletePermission(pageId, permissionType)
}

def deletePermission(Long pageId, String permissionType){
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

def contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
PageManager pageManager = ComponentLocator.getComponent(PageManager)
Page page = pageManager.getPage(pageId)

def permissions = contentPermissionManager.getContentPermissionSets(page, permissionType)

//Delete Permission
permissions.each{ permission ->
permission.each{ per ->
log.info("Deleted permission: " + per)
contentPermissionManager.removeContentPermission(per)
}
}
}

}

And then in the Job do this: 

package confluence

import com.atlassian.sal.api.component.ComponentLocator;
import com.atlassian.confluence.pages.PageManager;
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.confluence.pages.Page
import com.atlassian.confluence.core.ContentPermissionManager
import com.atlassian.confluence.security.ContentPermission
import confluence.RestrictionHandler

import static com.atlassian.confluence.security.ContentPermission.EDIT_PERMISSION
import static com.atlassian.confluence.security.ContentPermission.VIEW_PERMISSION

def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

def contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
PageManager pageManager = ComponentLocator.getComponent(PageManager)
RestrictionHandler handler = new RestrictionHandler()

hits.each { page ->
def pageId = page.getId() as Long
handler.deleteAllViewPermissionOnPage(pageId, ContentPermission.VIEW_PERMISSION)
handler.deleteAllEditPermissionOnPage(pageId, ContentPermission.EDIT_PERMISSION)
}

Can you try this, is this, what you wanted? 

Regards, Dominic

Like Patrick likes this
Patrick December 5, 2020

Hi @Dominic Lagger!

Thank you very much for the script, it is exactly what I was looking for. I've just tried to make some changes, because the requirements within my company changed slightly. The goal is now, to inherit the permissions from its parent, but your script was a great starting point to realize something like that:

package confluence

import com.atlassian.sal.api.component.ComponentLocator;
import com.atlassian.confluence.pages.PageManager;
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.confluence.pages.Page
import com.atlassian.confluence.core.ContentPermissionManager
import com.atlassian.confluence.security.ContentPermission

import static com.atlassian.confluence.security.ContentPermission.EDIT_PERMISSION
import static com.atlassian.confluence.security.ContentPermission.VIEW_PERMISSION

class RestrictionHandler {

def addAllViewPermissionFromParentOnPage(Long pageId, String permissionType)
{
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

addPermissionFromParent(pageId, permissionType)
}

def addAllEditPermissionFromParentOnPage(Long pageId, String permissionType)
{
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

addPermissionFromParent(pageId, permissionType)
}

def deleteAllViewPermissionOnPage(Long pageId, String permissionType)
{
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

deletePermission(pageId, permissionType)
}

def deleteAllEditPermissionOnPage(Long pageId, String permissionType)
{
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

deletePermission(pageId, permissionType)
}

def addPermissionFromParent(Long pageId, String permissionType) {
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

def contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
PageManager pageManager = ComponentLocator.getComponent(PageManager)
Page page = pageManager.getPage(pageId)

def permissions = contentPermissionManager.getContentPermissionSets(page, permissionType)

def parent = page.getParent()
def parentPermissions = contentPermissionManager.getContentPermissionSets(parent, permissionType)

// copy content permission from parent to actual page

parentPermissions.each
{
parentPermission ->
parentPermission.each
{
per ->
log.info("Added parent permission: " + per)
contentPermissionManager.addContentPermission(per, page.entity)
}
}

}

def deletePermission(Long pageId, String permissionType)
{
def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
log.setLevel(Level.INFO)

def contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
PageManager pageManager = ComponentLocator.getComponent(PageManager)
Page page = pageManager.getPage(pageId)

def permissions = contentPermissionManager.getContentPermissionSets(page, permissionType)

//Delete Permission
permissions.each
{
permission ->
permission.each
{
per ->
log.info("Deleted permission: " + per)
contentPermissionManager.removeContentPermission(per)
}
}
}
}

 

I've added a new method to add all permission of its parent. This works fine as well, but unfortunately with a small bug afterwards. :-D After removing the inherited restrictions from the parent, it breaks the space then, because of this error:

 

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.atlassian.confluence.security.ContentPermission#36798858]
    at org.hibernate.boot.internal.StandardEntityNotFoundDelegate.handleEntityNotFound(StandardEntityNotFoundDelegate.java:28)

But I will somehow fix that at this stage. For now I'm really happy for your input. Thank you very much!

 

Best regards,

Patrick

Like Dominic Lagger likes this
Tim Eddelbüttel
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 12, 2023

Hi @Patrick ,

can I ask how have you solved the issue after removing the inherited restriction?

I didn't find a solution yet.

Regards,
Tim

/Edit: Found the solution, simply flush the caches.

cacheManager.getCache("com.atlassian.confluence.security.ContentPermissionSet.contentPermissions").removeAll();
Like Patrick likes this

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events