I'm trying to write a script job to scan and delete attachment versions on a page.
For example on a page I have attach file A and reattach a few times to get 5 versions for file A. I want to write a script to delete the first 4 version.
Here's my attempt:
import com.atlassian.confluence.pages.Attachment
import com.atlassian.confluence.pages.AttachmentManager
import com.atlassian.sal.api.component.ComponentLocator
def attachmentManager = ComponentLocator.getComponent(AttachmentManager)
hits.each { attachment ->
def attachmentOnPage = attachmentManager.getAttachments(attachment)
if (attachmentOnPage.size() >1)
{
log.warn "attachmentOnPage: ${attachmentOnPage}"
log.warn "size: ${attachmentOnPage.size()}"
int size = attachmentOnPage.size()
int sizeMax = size - 1
List<String> attachmentDeleteList = new ArrayList<String>()
for(int i=0;i<size;i++)
{
if (i<sizeMax)
{
def attachmentSingle = attachmentOnPage.get(i)
attachmentDeleteList.add(attachmentSingle)
log.warn "attachmentDeleteList: ${attachmentDeleteList}"
//log.warn "attachmentSingle: ${attachmentSingle}"
//attachmentManager.removeAttachmentFromServer(attachmentSingle)
}
}
}
}
However, when I try to run the removeAttachmentFromServer method, it delete every versions and the file itself in the database. I also tried the removeAttachment(attachmentDeleteList) and it does the same thing. Is there any method that just delete the version not the attachment itself.
You can set retention rules to automatically remove attachments over a number/count.
Yes, this 'Confluence Retention Rule' feature is a very good addition to Confluence.
The only problem I have with it, is that it is not really about data retention, as it only works on historic data (versions older than the latest). And trash bin.
In our test, we found that the system needed 6 weeks to calm down. That is, after 6 weeks to total page size of the site did not change significantly anymore. I only checked total pages number and not total attachments number. I assume, as it is in the same process, the background process works on both items simultaneously.
The important message I would like to convey is:
Do not expect immediate results from this feature.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This REST Call is asking for confirmation. How to confirm it via script in Windows PowerShell?
https://www.your-conlfuence.com/pages/confirmattachmentversionremoval.action?pageId=######&fileName=<your file name>&version=n
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.pages.AttachmentManager
def attachments
def attachmentManager = ComponentLocator.getComponent(AttachmentManager)
def spaceManager = ComponentLocator.getComponent(SpaceManager)
def pageManager = ComponentLocator.getComponent(PageManager)
def space=spaceManager.getSpace('RUBIK')
def pages = pageManager.getPages(space, true)
for (page in pages) { //loop for every active page in the space
for (attachment in attachmentManager.getLatestVersionsOfAttachments(page)) { //list of latest attachments
attachmentManager.getPreviousVersions(attachment).each { //for every not latest version
attachmentManager.removeAttachmentVersionFromServer(it)
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
hi,
Thank you, the script is very useful.
Could anyone tell me how to modify this script to leave eg the last 5 versions of each attachment? I'm not a developer and I'm trying to modify it by trial and error.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Not final work, but only a concept. Good luck.
for (attachment in attachmentManager.getLatestVersionsOfAttachments(page)) { //list of latest attachments
def newestVersion = attachment.version //not sure if this is right field
attachmentManager.getPreviousVersions(attachment).each { //for every not latest version
//here need some logs to see if the results are sorted from the newest
//something like that:
if(it.version < newestVersion-5) {
attachmentManager.removeAttachmentVersionFromServer(it)
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I get the following error after each delete.
Object of class [com.atlassian.confluence.pages.Page] with identifier [6521421]: optimistic locking failed; nested exception is net.sf.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Page#6521421]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Well maybe it is easier to do via a REST call? The URL for deleting an attachment version takes the form of:
https://www.your-conlfuence.com/pages/confirmattachmentversionremoval.action?pageId=######&fileName=<your file name>&version=n
Where n is the version number. Now I don't know if you delete version 1, if the rest of the attachments will renumber so you will have to experiment (meaning you may have to delete version 1 four times in your case).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We would like to automate this using the scheduled script job in Scriptrunner though. I've managed to make my script works. Will post the answer here shortly.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey Nyugen,
Any chance you got this script working - looking to do something similar so would be a great help.
Thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've made it.
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.pages.AttachmentManager
def attachments
def attachmentManager = ComponentLocator.getComponent(AttachmentManager)
def spaceManager = ComponentLocator.getComponent(SpaceManager)
def pageManager = ComponentLocator.getComponent(PageManager)
def space=spaceManager.getSpace('RUBIK')
def pages = pageManager.getPages(space, true)
for (page in pages) { //loop for every active page in the space
for (attachment in attachmentManager.getLatestVersionsOfAttachments(page)) { //list of latest attachments
attachmentManager.getPreviousVersions(attachment).each { //for every not latest version
attachmentManager.removeAttachmentVersionFromServer(it)
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for this, quick question, do you know if this works fine on pages regardless of restrictions?
I've been looking at using the built in scripts but they have massive limitations, such as only showing (even to an admin) pages they have explicit access to. This is due to the built in script abiding by the confines of the quick search bar, that doesn't give admins search capability on something they don't have explicit access to. Then to make matters worse, when I tied to get the space owner to run it, it errors out.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Also, do you know whether or not this triggers the content updated notification email or not? A space owner was bombarded with the notification emails after we used the built in script, which isn't useful if we want to do this in the background for many spaces.
Is it possible you could put up a variation that runs across the entire instance?
thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This is working on admin permission of app. Doesn't look on restrictions.
I suggest to test it first on acc on few spaces. In some cases we have got problems with missing attachments.
About all spaces variant:
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.pages.AttachmentManager
def attachments
def attachmentManager = ComponentLocator.getComponent(AttachmentManager)
def spaceManager = ComponentLocator.getComponent(SpaceManager)
def pageManager = ComponentLocator.getComponent(PageManager)
def allSpaces = spaceManager.getAllSpaces()
for( def space : allSpaces)
{
def pages = pageManager.getPages(space, true)
for (page in pages) { //loop for every active page in the space
for (attachment in attachmentManager.getLatestVersionsOfAttachments(page)) { //list of latest attachments
attachmentManager.getPreviousVersions(attachment).each { //for every not latest version
attachmentManager.removeAttachmentVersionFromServer(it)
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Where do you run it from for it to not run as a regular user but to run as the system? Do you just put it in the jobs area of Scriptrunner? Although that does ask for a user to run as.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This script is based on java classes inside confluence. You need to run as Admin on Confluence to use it / run it.
Some scripts I think use current login user, other (script and function) doesn't need any authentication to run a code.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah ok so just stick it in the jobs area. It seems to slowly be running through it anyway, this ia n improvement over the Scriptrunner built in script as it always times out when using theirs because of proxy timeouts, even when raised to 10 minutes.
You may be able to help me with another issue. I need to bulk add a specific group to every page in my instance. Because of this issue:
https://jira.atlassian.com/browse/CONFSERVER-36393
But the script Adaptavist made for me doesn't work because of this issue:
https://jira.atlassian.com/browse/CONFSERVER-58536
This is the script below, do you have any ideas on how it could get to work?
import com.atlassian.confluence.core.ContentPermissionManager
import com.atlassian.confluence.pages.Page
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.security.ContentPermission
import com.atlassian.confluence.security.ContentPermissionSet
import com.atlassian.confluence.spaces.Space
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.sal.api.component.ComponentLocator
import static com.atlassian.confluence.security.ContentPermission.EDIT_PERMISSION
import static com.atlassian.confluence.security.ContentPermission.VIEW_PERMISSION
/**
* This script runs through all spaces and pages (with true parameter in getPages, eagerly fetch permissions at the same time)
* and assign view permission to the 'groupToAddPermission' variable. If this group already has View or edit permission,
* the script does not make any change
*/
SpaceManager spaceManager = ComponentLocator.getComponent(SpaceManager)
PageManager pageManager = ComponentLocator.getComponent(PageManager)
ContentPermissionManager contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
final String groupToAddPermission = 'confluence-administrators'
ContentPermission viewPermission = ContentPermission.createGroupPermission(VIEW_PERMISSION, groupToAddPermission)
ContentPermission editPermission = ContentPermission.createGroupPermission(EDIT_PERMISSION, groupToAddPermission)
log.error "view Permission ${viewPermission}"
log.error "edit Permission ${editPermission}"
spaceManager.allSpaces.each { Space space ->
log.error "Space ${space}"
if(space.key == '<KEY>'){
pageManager.getPages(space, true).each { Page page ->
log.error "Page ${page}"
ContentPermissionSet viewContentPermissionSet = page.getContentPermissionSet(VIEW_PERMISSION)
ContentPermissionSet editContentPermissionSet = page.getContentPermissionSet(EDIT_PERMISSION)
log.error "viewContentPermissionSet: ${viewContentPermissionSet}"
log.error "editContentPermissionSet: ${editContentPermissionSet}"
boolean containsGroupPermissions = viewContentPermissionSet?.contains(viewPermission) || editContentPermissionSet?.contains(editPermission)
boolean containsAnyRestrictions = viewContentPermissionSet || editContentPermissionSet
if (!containsGroupPermissions && containsAnyRestrictions) {
log.error "Assign new Content"
contentPermissionManager.addContentPermission(viewPermission, page)
log.error "viewContentPermissionSet Result1: ${ page.getContentPermissionSet(VIEW_PERMISSION)}"
log.error "editContentPermissionSet Result1: ${ page.getContentPermissionSet(EDIT_PERMISSION)}"
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Do you think you could combine your script with the one further up, so it can run on all pages and also keep the last 5 versions?
Been having trouble trying to combine the two myself.
thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
To be honest I don't have right now time to try this. From our side, we probably decided on that plugin. It can help us keeping always required numbers of old version pages.
Purge Versions for Confluence | Atlassian Marketplace
You can also try to use it as dry run.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.