• 20
    • 12
    • Our product teams collect and evaluate feedback from a number of different sources. To learn more about how we use customer feedback in the planning process, check out our new feature policy.

      NOTE: This suggestion is for Confluence Cloud. Using Confluence Server? See the corresponding suggestion.

      Deleted pages will go to Trash and remain there until a space admin clicks on Purge.

      This behaviour unfortunately may be obscure to some space administrators, plus it can be tedious to maintain manually.

      We need to create a function in Confluence to auto purge trash or perhaps create an option of how often the space admin would prefer trash to be purged.

        1. myaccount01.png
          myaccount01.png
          70 kB
        2. myaccount02.png
          myaccount02.png
          40 kB
        3. root.png
          root.png
          31 kB

            [CONFCLOUD-18160] Allow Confluence to auto purge trash over a period of time

            Igor K. added a comment -

            GDPR regulations (e.g. https://gdpr.eu/right-to-be-forgotten/) and security concerns indirectly require companies to remove both personal and non-personal data regularly, in order to comply with those. This was addressed and covered by Confluence server and DC editions, however cloud version does not support this.

            In real life, most Confluence space admins or users are not that knowledgeable to know that when they delete a page, it actually isn't really deleted and they need to request space or Confluence admins to purge the trash. This means that they may in good faith belive that they comply with the regulations, when actually they do not.

            Confluence admins should be responsible for higher level configuration, where retention rules could govern this, thus increasing security and privacy for all. I hope Atlassian will acknowledge how serious the lack of this feature is and implement it ASAP. 

            Igor K. added a comment - GDPR regulations (e.g. https://gdpr.eu/right-to-be-forgotten/) and security concerns indirectly require companies to remove both personal and non-personal data regularly, in order to comply with those. This was addressed and covered by Confluence server and DC editions, however cloud version does not support this. In real life, most Confluence space admins or users are not that knowledgeable to know that when they delete a page, it actually isn't really deleted and they need to request space or Confluence admins to purge the trash. This means that they may in good faith belive that they comply with the regulations, when actually they do not. Confluence admins should be responsible for higher level configuration, where retention rules could govern this, thus increasing security and privacy for all. I hope Atlassian will acknowledge how serious the lack of this feature is and implement it ASAP. 

            Insane this is not a feature already. How are their not more clean up options on cloud?

            Nathan Trout added a comment - Insane this is not a feature already. How are their not more clean up options on cloud?

            Thanks, Sam! Tested on 5.9.9, working nicely. I like the colored layout and configurable holding period. Can't believe this is not a feature in the default install. If you stumble onto this ticket through a search engine, please vote for it. Because life is really enough of a browser game already. Also lol at the ticket age.

            Stephan Eisvogel added a comment - Thanks, Sam! Tested on 5.9.9, working nicely. I like the colored layout and configurable holding period. Can't believe this is not a feature in the default install. If you stumble onto this ticket through a search engine, please vote for it. Because life is really enough of a browser game already. Also lol at the ticket age.

            Sam Hall added a comment -

            If the error page is an Apache one, then that's your culprit. There should be a directive in httpd.conf for that, I think it's called TimeOut.

            Sam Hall added a comment - If the error page is an Apache one, then that's your culprit. There should be a directive in httpd.conf for that, I think it's called TimeOut.

            Wondering if anyone else is getting a timeout error after 120 seconds. This might be a thing in our config behind a frontend Apache server...

            Jan-Peter Rusch added a comment - Wondering if anyone else is getting a timeout error after 120 seconds. This might be a thing in our config behind a frontend Apache server...

            Sam Hall added a comment -

            That icon worked for me too. Cheers!

            If you need any additional fixes or enhancements applied to the macro script, I'd suggest using the GitHub Issue Tracker.

            Sam Hall added a comment - That icon worked for me too. Cheers! If you need any additional fixes or enhancements applied to the macro script, I'd suggest using the GitHub Issue Tracker.

            Doug added a comment -

            Great work everyone!

            I have changed the icon text to use the same code as Atlassian uses in Confluence 5.9.7 and 5.10.4. I do not have an older version of Confluence to test, but this should also make the code work with future versions of Confluence.

            Remove this line
            <div style="margin-left:20px"><img alt="" src="/download/resources/com.atlassian.confluence.plugins.confluence-page-banner:page-banner-resources/images/grey_attach.png" height="16" width="16" title=""><i>$attId: $fname </i></div>
            
            Use this line
            <div style="margin-left:20px"><span class="icon icon-file-unknown" title="File">File</span><i>$attId: $fname </i></div>
            

            Doug added a comment - Great work everyone! I have changed the icon text to use the same code as Atlassian uses in Confluence 5.9.7 and 5.10.4. I do not have an older version of Confluence to test, but this should also make the code work with future versions of Confluence. Remove this line <div style= "margin-left:20px" ><img alt= "" src=" /download/resources/com.atlassian.confluence.plugins.confluence-page-banner:page-banner-resources/images/grey_attach.png " height=" 16 " width=" 16 " title=" "><i>$attId: $fname </i></div> Use this line <div style= "margin-left:20px" ><span class= "icon icon-file-unknown" title= "File" >File</span><i>$attId: $fname </i></div>

            No problem, it is a "cosmetic" issue.

            And thanks for the macro. I would not have done modifications if you had not written it.

            Pierre Lejeune added a comment - No problem, it is a "cosmetic" issue. And thanks for the macro. I would not have done modifications if you had not written it.

            Sam Hall added a comment -

            Oh, sorry. It was the attachment icon in 5.7.5, I was trying to be clever. I'll just change it to another li tag.

            I'm actually in the middle of running your version on my production server right now, 200 at a time. 400 pages done, 2500 to go....

            Thanks for contributing the modified date logic.

            Sam Hall added a comment - Oh, sorry. It was the attachment icon in 5.7.5, I was trying to be clever. I'll just change it to another li tag. I'm actually in the middle of running your version on my production server right now, 200 at a time. 400 pages done, 2500 to go.... Thanks for contributing the modified date logic.

            I am using Confluence 5.9.3 and /download/resources/com.atlassian.confluence.plugins.confluence-page-banner:page-banner-resources/images/grey_attach.png does not display any picture.

            Pierre Lejeune added a comment - I am using Confluence 5.9.3 and /download/resources/com.atlassian.confluence.plugins.confluence-page-banner:page-banner-resources/images/grey_attach.png does not display any picture.

            @SamHall, no problem for GitHub, good idea. Sorry for the late answer, I am from France...

            Pierre Lejeune added a comment - @SamHall, no problem for GitHub, good idea. Sorry for the late answer, I am from France...

            Thanks,

            didn't get any errors running the current version from GitHub.

            Jan-Peter Rusch added a comment - Thanks, didn't get any errors running the current version from GitHub.

            Sam Hall added a comment -

            I've put a version on GitHub which detects Attachment issues so it should not die with the 500 error page... https://github.com/Sam-Hall/purge-trash/blob/master/purge-trash.vm

            It's probably far less efficient now, but much safer.

            Currently it doesn't try to clean up the attachments in question, I somehow managed to corrupt things worse experimenting with some of the removeAttachement methods. So for now it only warns about the issues in bright red font.

            Sam Hall added a comment - I've put a version on GitHub which detects Attachment issues so it should not die with the 500 error page... https://github.com/Sam-Hall/purge-trash/blob/master/purge-trash.vm It's probably far less efficient now, but much safer. Currently it doesn't try to clean up the attachments in question, I somehow managed to corrupt things worse experimenting with some of the removeAttachement methods. So for now it only warns about the issues in bright red font.

            Sam Hall added a comment -

            @pierre.lejeune.groupeadsn1136641860 would you and Clement mind if I publish the macro via GitHub so it's easier to maintain?

            Sam Hall added a comment - @pierre.lejeune.groupeadsn1136641860 would you and Clement mind if I publish the macro via GitHub so it's easier to maintain?

            Sam Hall added a comment - - edited
            set def off;
            
            SELECT c1.TITLE, '/pages/confirmattachmentremoval.action?pageId='||c1.pageid||'&fileName='||c1.title
            FROM CONTENT C1, content c2
            WHERE C1.CONTENTTYPE = 'ATTACHMENT'
            and  C2.CONTENTTYPE = 'ATTACHMENT'
            and c1.title = c2.title
            and c1.version = c2.version
            and c1.pageid = c2.pageid
            and c1.contentid != c2.contentid
            and c1.contentid > c2.contentid;
            
            
            

            This is the query for Oracle DB to list the delete attachment page for all duplicated attachments.

            I was able to cause a duplicated attachment to occur on 5.7.5, and it seems there is an outstanding bug related to this issue, which Atlassian have closed prematurely... https://jira.atlassian.com/browse/CONF-7882

             

            Sam Hall added a comment - - edited set def off; SELECT c1.TITLE, '/pages/confirmattachmentremoval.action?pageId=' ||c1.pageid|| '&fileName=' ||c1.title FROM CONTENT C1, content c2 WHERE C1.CONTENTTYPE = 'ATTACHMENT' and  C2.CONTENTTYPE = 'ATTACHMENT' and c1.title = c2.title and c1.version = c2.version and c1.pageid = c2.pageid and c1.contentid != c2.contentid and c1.contentid > c2.contentid; This is the query for Oracle DB to list the delete attachment page for all duplicated attachments. I was able to cause a duplicated attachment to occur on 5.7.5, and it seems there is an outstanding bug related to this issue, which Atlassian have closed prematurely... https://jira.atlassian.com/browse/CONF-7882  

            Sam Hall added a comment -

            We had some errors too, but I didn't realise it would be a common issue for people. See my comments here regarding tracking these down... https://answers.atlassian.com/questions/88928/answers/40348119

            I have a better query than the one listed there that outputs the "delete attachment" link for each duplicate, I'll post that later.

            As a work around, the Macro could be modified to delete all the Attachments from a page before performing the purge.

            Sam Hall added a comment - We had some errors too, but I didn't realise it would be a common issue for people. See my comments here regarding tracking these down... https://answers.atlassian.com/questions/88928/answers/40348119 I have a better query than the one listed there that outputs the "delete attachment" link for each duplicate, I'll post that later. As a work around, the Macro could be modified to delete all the Attachments from a page before performing the purge.

            Doug added a comment -

            Thank you samhall, Clement Martino, and pierre.lejeune.groupeadsn1136641860 for the work!

            rs1,
            I am experiencing that error also, but I think it is related to files/pages with the same name in the trash. Each time I experienced the error, I then tried purging fewer items until I got to purging one item at a time. Then I could get past the error and resume purging 100 items at a time. Maybe a fix would be to run thru the itemList once to remove any duplicates. Then worst case for a user to purge all items in the trash would require them to run the macro a minimum of times as the highest number of occurrences of a duplicate name in a space trash.

            Also, I did all of this on a testing environment with much less resources available than our production environment. At one time I found a page in the trash that resulted in a 500 error when using the user-macro and internal system errors when using the GUI to purge the page. The fix required I add a few GB to the JAVA heap size. Going from 4GB to 8GB JAVA heap still took 6 minutes and 30 seconds to purge that one, extremely large page.

            Doug added a comment - Thank you samhall , Clement Martino, and pierre.lejeune.groupeadsn1136641860 for the work! rs1 , I am experiencing that error also, but I think it is related to files/pages with the same name in the trash. Each time I experienced the error, I then tried purging fewer items until I got to purging one item at a time. Then I could get past the error and resume purging 100 items at a time. Maybe a fix would be to run thru the itemList once to remove any duplicates. Then worst case for a user to purge all items in the trash would require them to run the macro a minimum of times as the highest number of occurrences of a duplicate name in a space trash. Also, I did all of this on a testing environment with much less resources available than our production environment. At one time I found a page in the trash that resulted in a 500 error when using the user-macro and internal system errors when using the GUI to purge the page. The fix required I add a few GB to the JAVA heap size. Going from 4GB to 8GB JAVA heap still took 6 minutes and 30 seconds to purge that one, extremely large page.

            It would be nice to name the Confluence version this macro supports. Running this on a 5.9.11 in non-demo mode returns an error 500 with some Collection already evicted errors in log.

            Summary:

            2016-08-31 17:32:10,451 ERROR [ajp-nio-192.168.2.188-8009-exec-7] [opensymphony.webwork.dispatcher.VelocityResult] doExecute Unable to render Velocity Template, '/pages/viewpage.vm'
             -- referer: https://XXXXXXXXX/confluence/display/XXXXXX/XXXXXXXX | url: /confluence/pages/viewpage.action | userName: admin | action: viewpage | page: 210665658
            java.lang.RuntimeException: Error rendering template for decorator root
                ...
            Caused by: java.lang.RuntimeException: Error rendering template for decorator page
                ...
            Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getDisplayableLabel' in  class com.atlassian.confluence.plugin.descriptor.web.model.ConfluenceWebLabel threw exception com.atlassian.core.exception.InfrastructureException: Error occurred rendering template content at template/includes/menu-macros.vm[line 321, column 36]
                ... 372 more
            Caused by: com.atlassian.core.exception.InfrastructureException: Error occurred rendering template content
                ... 415 more
            Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getLatestVersionsOfAttachments' in  class com.atlassian.confluence.pages.Page threw exception net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection at getRenderedContent[line 1, column 15]
                ... 430 more
            Caused by: net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection
                ... 438 more
            Caused by: net.sf.hibernate.HibernateException: collection was evicted
                ... 451 more
            
            

            Jan-Peter Rusch added a comment - It would be nice to name the Confluence version this macro supports. Running this on a 5.9.11 in non-demo mode returns an error 500 with some Collection already evicted errors in log. Summary: 2016-08-31 17:32:10,451 ERROR [ajp-nio-192.168.2.188-8009-exec-7] [opensymphony.webwork.dispatcher.VelocityResult] doExecute Unable to render Velocity Template, '/pages/viewpage.vm'  -- referer: https: //XXXXXXXXX/confluence/display/XXXXXX/XXXXXXXX | url: /confluence/pages/viewpage.action | userName: admin | action: viewpage | page: 210665658 java.lang.RuntimeException: Error rendering template for decorator root     ... Caused by: java.lang.RuntimeException: Error rendering template for decorator page     ... Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getDisplayableLabel' in  class com.atlassian.confluence.plugin.descriptor.web.model.ConfluenceWebLabel threw exception com.atlassian.core.exception.InfrastructureException: Error occurred rendering template content at template/includes/menu-macros.vm[line 321, column 36]     ... 372 more Caused by: com.atlassian.core.exception.InfrastructureException: Error occurred rendering template content     ... 415 more Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getLatestVersionsOfAttachments' in  class com.atlassian.confluence.pages.Page threw exception net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection at getRenderedContent[line 1, column 15]     ... 430 more Caused by: net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection     ... 438 more Caused by: net.sf.hibernate.HibernateException: collection was evicted     ... 451 more

            Pierre Lejeune added a comment - - edited

            We (I have asked some help to a Java developer, I don't know Java...) have worked with LastModificationDate:

            # Macro Name: purge-trash
            ## Visibility: Visible only to system administrators in the Macro Browser
            ## Macro Title: Purge Trash
            ## Description: Embed this in a page and view it to purge all trash in all spaces
            ## Categories: Administration
            ## Macro body: No
            ##
            ## Developed by: Sam Hall, Clement Martino and Pierre Lejeune
            ## Source : https://jira.atlassian.com/browse/CONF-18160?focusedCommentId=952259&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-952259
            ## Date created: 31/08/2016
            ## Installed by: Pierre Lejeune
            
            ## @param simulate:title=Simulate Only|type=boolean|required=true|desc=Don't actually purge anything|default=true
            ## @param limit:title=Limit|type=int|required=false|desc=Limit the max number of pages to purge (default 100)
            ## @param days:title=Days|type=int|required=false|desc=Define the period to keep documents (default 90)
            
            #if($permissionHelper.isConfluenceAdministrator($action.remoteUser) == "true")
            
                #set($containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager'))
                #set($getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null))
                #set($containerManager=$getInstanceMethod.invoke(null,null))
                #set($containerContext=$containerManager.containerContext)
            
                #set($Integer = 0)
                #set($Long = $Integer.longValue())
                #set($trashManager=$containerContext.getComponent('trashManager'))
                #set($spaceManager=$containerContext.getComponent('spaceManager'))
            
                #set($spaces = $spaceManager.getAllSpaces())
                #set($spaceCount = 0)
                #set($purgeCount = 0)
            
            ## Defaults
                #if (!$paramsimulate)
                    #set ($paramsimulate="true")
                #end
                #if (!$paramlimit)
                    #set ($purgeLimit=100)
                #else
                    #set ($purgeLimit=$Integer.parseInt($paramlimit))
                #end
                #if (!$paramdays)
                    #set ($purgeDays=90)
                #else
                    #set ($purgeDays=$Integer.parseInt($paramdays))
                #end
            
                #set($delay = $purgeDays*24*3600*1000)
                #set($today = $content.currentDate.time)
                #set($date_limit = $today - $delay)
            
            <b>Purge Trash invoked (simulate = $paramsimulate, limit = $purgeLimit, days = $purgeDays)</b>
            <hr/>
            
                #foreach($space in $spaces)
                    #set($spaceKey = $space.key)
                    #set($items = $trashManager.getNumberOfItemsInTrash($space))
            
                    #if ($items > 0 && $purgeCount < $purgeLimit)
                    <b>Found $items trash items in space: $spaceKey</b><br/>
                        #set($itemList = $trashManager.getTrashContents($space,0,$items))
                    <ul>
                        #foreach($item in $itemList)
                            #set($title = $item.getDisplayTitle())
                            #set($contentId = $item.getIdAsString())
                            #set($moddate = $item.getLastModificationDate())
                            <li/>$moddate - $contentId: $title
            
                            #if ($moddate.time < $date_limit)
                                #if ($purgeCount < $purgeLimit)
                                    #if ($paramsimulate != "true")
                                        #set($bool = $trashManager.purge($spaceKey, $Long.parseLong($contentId)))
                                    #end
                                    #if ($bool == "true" || $paramsimulate == "true")
                                        #set($purgeCount = $purgeCount+1)
                                        <b> PURGED OK</b>
                                        #if ($purgeCount >= $purgeLimit)
                                            <b> - PURGE LIMIT REACHED</b>
                                        #end
                                    #end
                                #end
                            #else
                                <b> TOO RECENT</b>
                            #end
                            </li>
                        #end
                    </ul>
                        #set($spaceCount = $spaceCount+1)
                    <hr/>
                    #end
                #end
            
            <b>Emptied $purgeCount trash items from $spaceCount spaces.</b><br/>
            #else
            <b>Purge Trash may only be performed by a Confluence Administrator.</b>
            #end
            
            
            

            Pierre Lejeune added a comment - - edited We (I have asked some help to a Java developer, I don't know Java...) have worked with LastModificationDate: # Macro Name: purge-trash ## Visibility: Visible only to system administrators in the Macro Browser ## Macro Title: Purge Trash ## Description: Embed this in a page and view it to purge all trash in all spaces ## Categories: Administration ## Macro body: No ## ## Developed by: Sam Hall, Clement Martino and Pierre Lejeune ## Source : https: //jira.atlassian.com/browse/CONF-18160?focusedCommentId=952259&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-952259 ## Date created: 31/08/2016 ## Installed by: Pierre Lejeune ## @param simulate:title=Simulate Only|type= boolean |required= true |desc=Don't actually purge anything| default = true ## @param limit:title=Limit|type= int |required= false |desc=Limit the max number of pages to purge ( default 100) ## @param days:title=Days|type= int |required= false |desc=Define the period to keep documents ( default 90) # if ($permissionHelper.isConfluenceAdministrator($action.remoteUser) == " true " ) #set($containerManagerClass=$content. class. forName( 'com.atlassian.spring.container.ContainerManager' )) #set($getInstanceMethod=$containerManagerClass.getDeclaredMethod( 'getInstance' , null )) #set($containerManager=$getInstanceMethod.invoke( null , null )) #set($containerContext=$containerManager.containerContext) #set($ Integer = 0) #set($ Long = $ Integer .longValue()) #set($trashManager=$containerContext.getComponent( 'trashManager' )) #set($spaceManager=$containerContext.getComponent( 'spaceManager' )) #set($spaces = $spaceManager.getAllSpaces()) #set($spaceCount = 0) #set($purgeCount = 0) ## Defaults # if (!$paramsimulate) #set ($paramsimulate= " true " ) #end # if (!$paramlimit) #set ($purgeLimit=100) # else #set ($purgeLimit=$ Integer .parseInt($paramlimit)) #end # if (!$paramdays) #set ($purgeDays=90) # else #set ($purgeDays=$ Integer .parseInt($paramdays)) #end #set($delay = $purgeDays*24*3600*1000) #set($today = $content.currentDate.time) #set($date_limit = $today - $delay) <b>Purge Trash invoked (simulate = $paramsimulate, limit = $purgeLimit, days = $purgeDays)</b> <hr/> #foreach($space in $spaces) #set($spaceKey = $space.key) #set($items = $trashManager.getNumberOfItemsInTrash($space)) # if ($items > 0 && $purgeCount < $purgeLimit) <b>Found $items trash items in space: $spaceKey</b><br/> #set($itemList = $trashManager.getTrashContents($space,0,$items)) <ul> #foreach($item in $itemList) #set($title = $item.getDisplayTitle()) #set($contentId = $item.getIdAsString()) #set($moddate = $item.getLastModificationDate()) <li/>$moddate - $contentId: $title # if ($moddate.time < $date_limit) # if ($purgeCount < $purgeLimit) # if ($paramsimulate != " true " ) #set($bool = $trashManager.purge($spaceKey, $ Long .parseLong($contentId))) #end # if ($bool == " true " || $paramsimulate == " true " ) #set($purgeCount = $purgeCount+1) <b> PURGED OK</b> # if ($purgeCount >= $purgeLimit) <b> - PURGE LIMIT REACHED</b> #end #end #end # else <b> TOO RECENT</b> #end </li> #end </ul> #set($spaceCount = $spaceCount+1) <hr/> #end #end <b>Emptied $purgeCount trash items from $spaceCount spaces.</b><br/> # else <b>Purge Trash may only be performed by a Confluence Administrator.</b> #end

            Thanks, I will have a look and will be back if I found something.

            Pierre Lejeune added a comment - Thanks, I will have a look and will be back if I found something.

            Sam Hall added a comment -

            I don't think it's stored anywhere, I can't see any "deleted" date... https://docs.atlassian.com/confluence/5.9.5/com/atlassian/confluence/core/ContentEntityObject.html

            Unless it's something you can access via getProperties, but I didn't notice a deleted date even when poking around in the database.

            These methods are not hyperlinked and I didn't really care enough to look much further, but you could have a play with these "Methods inherited from class com.atlassian.core.bean.EntityObject":
            getCreationDate, getCurrentDate, getLastModificationDate

            In the Velocity syntax, you'd probably have to toString these if they are dates and then manipulate them as strings.

            Sam Hall added a comment - I don't think it's stored anywhere, I can't see any "deleted" date... https://docs.atlassian.com/confluence/5.9.5/com/atlassian/confluence/core/ContentEntityObject.html Unless it's something you can access via getProperties, but I didn't notice a deleted date even when poking around in the database. These methods are not hyperlinked and I didn't really care enough to look much further, but you could have a play with these "Methods inherited from class com.atlassian.core.bean.EntityObject": getCreationDate, getCurrentDate, getLastModificationDate In the Velocity syntax, you'd probably have to toString these if they are dates and then manipulate them as strings.

            Thanks, it works well.
            I have searched but not found, if it is possible de delete only older documents from trash.
            Do you know if we can get the delete date of a document?
            Anyway thanks again for this macro.

            Pierre Lejeune added a comment - Thanks, it works well. I have searched but not found, if it is possible de delete only older documents from trash. Do you know if we can get the delete date of a document? Anyway thanks again for this macro.

            Sam Hall added a comment - - edited

            Here's a User Macro that purges everything...

            ## Macro Name: purge-trash
            ## Visibility: Visible only to system administrators in the Macro Browser
            ## Macro Title: Purge Trash
            ## Description: Embed this in a page and view it to purge all trash in all spaces
            ## Categories: Administration
            ## Macro body: No
            ##
            ## Developed by: Sam Hall
            ## Date created: 31/08/2016
            ## Installed by: Sam Hall
            
            ## @param simulate:title=Simulate Only|type=boolean|required=true|desc=Don't actually purge anything|default=true
            ## @param limit:title=Limit|type=int|required=false|desc=Limit the max number of pages to purge (default 100)
            
            #if($permissionHelper.isConfluenceAdministrator($action.remoteUser) == "true")
            
            #set($containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager'))
            #set($getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null))
            #set($containerManager=$getInstanceMethod.invoke(null,null))
            #set($containerContext=$containerManager.containerContext)
            
            #set($Integer = 0)
            #set($Long = $Integer.longValue())
            #set($trashManager=$containerContext.getComponent('trashManager'))
            #set($spaceManager=$containerContext.getComponent('spaceManager'))
            
            #set($spaces = $spaceManager.getAllSpaces())
            #set($spaceCount = 0)
            #set($purgeCount = 0)
            
            ## Defaults
            #if (!$paramsimulate)
              #set ($paramsimulate="true")
            #end
            #if (!$paramlimit)
              #set ($purgeLimit=100)
            #else
              #set ($purgeLimit=$Integer.parseInt($paramlimit))
            #end
            
            <b>Purge Trash invoked (simulate = $paramsimulate, limit = $purgeLimit)</b><hr/>
            
            #foreach($space in $spaces)
              #set($spaceKey = $space.key)
              #set($items = $trashManager.getNumberOfItemsInTrash($space))
            
              #if ($items > 0 && $purgeCount < $purgeLimit)
                <b>Found $items trash items in space: $spaceKey</b><br/>
                #set($itemList = $trashManager.getTrashContents($space,0,$items))
                <ul>
                #foreach($item in $itemList)
                  #set($title = $item.getDisplayTitle())
                  #set($contentId = $item.getIdAsString())
                  <li/>$contentId: $title
            
                  #if ($purgeCount < $purgeLimit)
                    #if ($paramsimulate != "true")
                      #set($bool = $trashManager.purge($spaceKey, $Long.parseLong($contentId)))
                    #end
                    #if ($bool == "true" || $paramsimulate == "true")
                      #set($purgeCount = $purgeCount+1)
                      <b> PURGED OK</b>
                      #if ($purgeCount >= $purgeLimit)
                        <b> - PURGE LIMIT REACHED</b>
                      #end
                    #end
                  #end
                  </li>
                #end
                </ul>
                #set($spaceCount = $spaceCount+1)
                <hr/>
              #end
            #end
            
            <b>Emptied $purgeCount trash items from $spaceCount spaces.</b><br/>
            #else
            <b>Purge Trash may only be performed by a Confluence Administrator.</b>
            #end
            
            
            

            Sam Hall added a comment - - edited Here's a User Macro that purges everything... ## Macro Name: purge-trash ## Visibility: Visible only to system administrators in the Macro Browser ## Macro Title: Purge Trash ## Description: Embed this in a page and view it to purge all trash in all spaces ## Categories: Administration ## Macro body: No ## ## Developed by: Sam Hall ## Date created: 31/08/2016 ## Installed by: Sam Hall ## @param simulate:title=Simulate Only|type= boolean |required= true |desc=Don't actually purge anything| default = true ## @param limit:title=Limit|type= int |required= false |desc=Limit the max number of pages to purge ( default 100) # if ($permissionHelper.isConfluenceAdministrator($action.remoteUser) == " true " ) #set($containerManagerClass=$content. class. forName( 'com.atlassian.spring.container.ContainerManager' )) #set($getInstanceMethod=$containerManagerClass.getDeclaredMethod( 'getInstance' , null )) #set($containerManager=$getInstanceMethod.invoke( null , null )) #set($containerContext=$containerManager.containerContext) #set($ Integer = 0) #set($ Long = $ Integer .longValue()) #set($trashManager=$containerContext.getComponent( 'trashManager' )) #set($spaceManager=$containerContext.getComponent( 'spaceManager' )) #set($spaces = $spaceManager.getAllSpaces()) #set($spaceCount = 0) #set($purgeCount = 0) ## Defaults # if (!$paramsimulate)   #set ($paramsimulate= " true " ) #end # if (!$paramlimit)   #set ($purgeLimit=100) # else   #set ($purgeLimit=$ Integer .parseInt($paramlimit)) #end <b>Purge Trash invoked (simulate = $paramsimulate, limit = $purgeLimit)</b><hr/> #foreach($space in $spaces)   #set($spaceKey = $space.key)   #set($items = $trashManager.getNumberOfItemsInTrash($space))   # if ($items > 0 && $purgeCount < $purgeLimit)     <b>Found $items trash items in space: $spaceKey</b><br/>     #set($itemList = $trashManager.getTrashContents($space,0,$items))     <ul>     #foreach($item in $itemList)       #set($title = $item.getDisplayTitle())       #set($contentId = $item.getIdAsString())       <li/>$contentId: $title       # if ($purgeCount < $purgeLimit)         # if ($paramsimulate != " true " )           #set($bool = $trashManager.purge($spaceKey, $ Long .parseLong($contentId)))         #end         # if ($bool == " true " || $paramsimulate == " true " )           #set($purgeCount = $purgeCount+1)           <b> PURGED OK</b>           # if ($purgeCount >= $purgeLimit)             <b> - PURGE LIMIT REACHED</b>           #end         #end       #end       </li>     #end     </ul>     #set($spaceCount = $spaceCount+1)     <hr/>   #end #end <b>Emptied $purgeCount trash items from $spaceCount spaces.</b><br/> # else <b>Purge Trash may only be performed by a Confluence Administrator.</b> #end

            Andre Lehmann added a comment - - edited

            We also do it with the CLI but we purge everything, not only the oldest things. => makes it easier to script
            Script runs every 6 months:

             --action runFromSpacelist --common '--action removeTrash --space @space@ --connectionTimeout 0'
            

            Andre Lehmann added a comment - - edited We also do it with the CLI but we purge everything, not only the oldest things. => makes it easier to script Script runs every 6 months: --action runFromSpacelist --common '--action removeTrash --space @space@ --connectionTimeout 0'

            We do it with CLI, too. But should be a feature of Confluence.

            Thomas Liskow added a comment - We do it with CLI, too. But should be a feature of Confluence.

            Hi Paul,

            I am interested to see your script. Is it possible?

            Regards,

            Pierre Lejeune added a comment - Hi Paul, I am interested to see your script. Is it possible? Regards,

            Regis added a comment -

            You're right, Robert, so do I. Long Live CLI I did quite the same. But well, from an admin point of view, I think that kind od feature could really be integrated in the Confluence admin; managing trashes is identified as one of the things to be done, when you want to garantee good performances to your users, and it is a pity not to be provided with a on-the-shelve stuff to do it...

            Regis added a comment - You're right, Robert, so do I. Long Live CLI I did quite the same. But well, from an admin point of view, I think that kind od feature could really be integrated in the Confluence admin; managing trashes is identified as one of the things to be done, when you want to garantee good performances to your users, and it is a pity not to be provided with a on-the-shelve stuff to do it...

            Ben Wardwell (Inactive) added a comment - - edited

            Using the CLI and some fancy scripting I implemented a procedure like the above requested. It will getTrashList and put that into a file and then parse the list with sed/awk and get the ID ($1) and get the Modified date ($7). If no modified date is found it will use the create date ($5) and then compare that to the date passed in English/Unix text (EG "1 month ago", "1 year ago") and if the date is before then, then remove the piece of trash by id:
            ./confluence.sh --action removeTrash --id 75106089 --space ZConfSpace
            And doing this via a cronjob it is completely automated.

            Love the CLI

            Ben Wardwell (Inactive) added a comment - - edited Using the CLI and some fancy scripting I implemented a procedure like the above requested. It will getTrashList and put that into a file and then parse the list with sed/awk and get the ID ($1) and get the Modified date ($7). If no modified date is found it will use the create date ($5) and then compare that to the date passed in English/Unix text (EG "1 month ago", "1 year ago") and if the date is before then, then remove the piece of trash by id: ./confluence.sh --action removeTrash --id 75106089 --space ZConfSpace And doing this via a cronjob it is completely automated. Love the CLI

            Definitely would like to have this feature.

            andrew corley added a comment - Definitely would like to have this feature.

            Completely Agree. We definitely need this feature as it takes a lot of time for Admins to go manually and purge the trash. Hope Atlassian can build something like this.

            Sagar Shaha added a comment - Completely Agree. We definitely need this feature as it takes a lot of time for Admins to go manually and purge the trash. Hope Atlassian can build something like this.

            1. I do it via https://jira.atlassian.com/browse/CONF-30043. I find that myaccount can't run the script(myaccount01.png), it is fine if I use root account(root.png). But my account is also administrator(myaccount02.png). Why?

            2. The above is also done manually, I hope I can do it termly.

            David David added a comment - 1. I do it via https://jira.atlassian.com/browse/CONF-30043 . I find that myaccount can't run the script(myaccount01.png), it is fine if I use root account(root.png). But my account is also administrator(myaccount02.png). Why? 2. The above is also done manually, I hope I can do it termly.

            1. Periodically deleting ALL trashed pages is not an option as it would deprive the user of the possibility to restore recently deleted pages. Thus we need a logic which deletes trash content according to when it was deleted.

            2. Please keep in mind that the average space admin does not care about the data garbage lying around in his trash. It is the application administrator who has to take care that an installation doesn't get cluttered. So it must be in the general administration console that this option can be configured.

            Karola Schaeuble added a comment - 1. Periodically deleting ALL trashed pages is not an option as it would deprive the user of the possibility to restore recently deleted pages. Thus we need a logic which deletes trash content according to when it was deleted. 2. Please keep in mind that the average space admin does not care about the data garbage lying around in his trash. It is the application administrator who has to take care that an installation doesn't get cluttered. So it must be in the general administration console that this option can be configured.

            Just to give a possible alternative for this: you may try using the Confluence CLI which has getTrashList and removeTrash functions. Combining the two in a cron script or other scheduler job can very well do the job.

            Peter Koczan (Inactive) added a comment - Just to give a possible alternative for this: you may try using the Confluence CLI which has getTrashList and removeTrash functions. Combining the two in a cron script or other scheduler job can very well do the job.

            I completely agree with the others: Having confluence to automatically purge items from trash having been in trash for more than X days is mandatory in an environment as ours: We have around 150k (current) pages, about 25k of them are in trash and no one removing them.

            Michael Rieger added a comment - I completely agree with the others: Having confluence to automatically purge items from trash having been in trash for more than X days is mandatory in an environment as ours: We have around 150k (current) pages, about 25k of them are in trash and no one removing them.

            No plan for implementing this? Our Conlfuence instance is so much blown up also because of non purged content ion Trash.

            Michael Michael added a comment - No plan for implementing this? Our Conlfuence instance is so much blown up also because of non purged content ion Trash.

            I like the features requested above. What would really help me is a global "purge deleted pages" that would in one step allow the system admin to purge deleted pages across all spaces or a subset of spaces.

            Mitchell Ashley added a comment - I like the features requested above. What would really help me is a global "purge deleted pages" that would in one step allow the system admin to purge deleted pages across all spaces or a subset of spaces.

            This would be a great feature, I don't think most of our users even know there is a trash can that needs to be purged. Another option would be to have a global setting for the number of day something will stay in the trash before automatic purging. For example have a "Max Days in Trash" setting so if it is set to 14, so things will only sit in the trash for a max of 14 days before automatically being purged.

            Mark Liedtke added a comment - This would be a great feature, I don't think most of our users even know there is a trash can that needs to be purged. Another option would be to have a global setting for the number of day something will stay in the trash before automatic purging. For example have a "Max Days in Trash" setting so if it is set to 14, so things will only sit in the trash for a max of 14 days before automatically being purged.

            Fully agree, exactly the functionality I search for at the moment. It would also be nice to have the possibilty for the Confluence Admin to purge a Trash folder at once. We see that the Space Admins are not aware of purging the Trash.

            Jositz, Michael (Allianz SE) added a comment - Fully agree, exactly the functionality I search for at the moment. It would also be nice to have the possibilty for the Confluence Admin to purge a Trash folder at once. We see that the Space Admins are not aware of purging the Trash.

              62c32a53ff47 John Hooper
              rhartono Roy Hartono [Atlassian]
              Votes:
              123 Vote for this issue
              Watchers:
              84 Start watching this issue

                Created:
                Updated: