Change Document User

Last modified by Clemens Robbenhaar on 2024/07/22 00:03

user_goReplace all occurences of the old user with the new user for the selected fields of existing documents.
TypeXAR
CategoryApplication
Developed byUnknown
Active Installs31
Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

Installable with the Extension Manager

Description

Replace all occurences of the old user with the new user for the selected fields of existing documents inside the current wiki. If this extension is used in the main wiki, one can optionally do the replacement in all subwikis, too.

Based on the affected fields, this will also grant the affected documents the rights of the new user, instead of the old one's:

  • contentAuthor: Gives affected document Programming or Script rights, if the new user has them, allowing existing scripts or protected API calls inside that document to be executed when the document is viewed.
  • author: Gives affected document Admin or Programming rights, if the new user has them, allowing special objects (wiki macros, wiki components, UIX, translations) to be registered at a wiki or global level. Also updates the value displayed on the document's "Last modified by" section with the new user.
  • creator: Gives delete right for the document to the new user. Also updates the value displayed on the documents "Created by" section with the new user.

Note: To list the content author users you can use the List Deleted Document Users application.

Requires Programming Rights to function.

Step1:
changeDocumentUser.png

Step2:
changeDocumentUser-confirm.png

Step3:
changeDocumentUser-result.png

Source

Below is the source to copy/paste in a new document in your XWiki instance, in case you can/will not use Extension Manager or direct XAR import to install it.

{{velocity}}
#set ($oldUser = "$!request.oldUser")
#set ($newUser = "$!request.newUser")
#set ($fields = $request.getParameterValues('field'))
#set ($fields = $fields.subList(0, $fields.size()))
#set ($wantSubWikis = ("$!request.subwikis" != ""))
#set($mainWikiId = $services.wiki.getMainWikiId())
#set($currentWikiId = $services.wiki.getCurrentWikiId())
#set($hasSubWikis = ($currentWikiId == $mainWikiId) && $services.wiki.getAllIds().size() > 1)
##
#if ($oldUser != '' && $newUser != '' && "$!fields" != '')
  #set($documentsPerWikiToUpdate = {})
  #set($documentsToUpdate = [])
  #macro (getDocumentToUpdateFromWiki $oldUser $wikiId)
    ## Build and run the query
    #set ($documentsToUpdateQuery = "SELECT doc.fullName, doc.author, doc.contentAuthor, doc.creator FROM Document doc WHERE ")
    #foreach ($field in $fields)
      #if ($foreach.count > 1)
        #set ($documentsToUpdateQuery = "${documentsToUpdateQuery} OR ")
      #end
      #set ($documentsToUpdateQuery = "${documentsToUpdateQuery} doc.${field}=:oldUser")
    #end
    #set ($documentsToUpdateQuery = "${documentsToUpdateQuery} ORDER BY doc.fullName ASC")
    #set($documentsToUpdate = $services.query.xwql($documentsToUpdateQuery).setWiki($wikiId).bindValue('oldUser', $oldUser).execute())
    #set($discard = $documentsPerWikiToUpdate.put($wikiId, $documentsToUpdate))
    #set($docCount = $docCount + $documentsToUpdate.size())
  #end
  ##
  #macro (getMatchedFields $queryResultRow $oldUser)
    #set ($matchedFields = [])
    #if ($queryResultRow[1] == $oldUser && $fields.contains('author'))
      #set ($discard = $matchedFields.add('author'))
    #end
    #if ($queryResultRow[2] == $oldUser && $fields.contains('contentAuthor'))
      #set ($discard = $matchedFields.add('contentAuthor'))
    #end
    #if ($queryResultRow[3] == $oldUser && $fields.contains('creator'))
      #set ($discard = $matchedFields.add('creator'))
    #end
  #end
  ##
  #set($docCount = 0)
  #if($hasSubWikis && $wantSubWikis)
    #foreach($wikiId in $services.wiki.getAllIds())
       #if($wikiId == $mainWikiId)
         #getDocumentToUpdateFromWiki($oldUser $wikiId)
       #else
         #getDocumentToUpdateFromWiki("${mainWikiId}:$oldUser" $wikiId)
       #end
       #set($docCount = $docCount + $documentsToUpdate.size())
    #end
  #else
    #getDocumentToUpdateFromWiki($oldUser $currentWikiId)
  #end
  #set ($newUserReference = $services.model.resolveDocument($newUser))
  ##
  #if ($request.confirm == 'true')
    #foreach($wikiId in $documentsPerWikiToUpdate.keySet())
      #set($documentsToUpdate = $documentsPerWikiToUpdate.get($wikiId))
      #set($prefixUser = "")
      #set($prefixPage = "")
      #if($hasSubWikis && $wikiId != $mainWikiId)
        #set($prefixUser = "${mainWikiId}:")
        #set($prefixPage = "${wikiId}:")
        #set($discard = $xcontext.setDatabase($wikiId))
      #end
      #foreach ($documentToUpdate in $documentsToUpdate)
        #getMatchedFields($documentToUpdate "${prefixUser}$oldUser")
        ##
        #set ($document = $xwiki.getDocument($documentToUpdate[0]))
        #set ($protectedDocument = $document.document)
        ## Update the requested document user fields with the new user reference.
        #if ($matchedFields.contains('author'))
          #set ($discard = $protectedDocument.setAuthorReference($newUserReference))
        #end
        #if ($matchedFields.contains('contentAuthor'))
          #set ($discard = $protectedDocument.setContentAuthorReference($newUserReference))
        #end
        #if ($matchedFields.contains('creator'))
          #set ($discard = $protectedDocument.setCreatorReference($newUserReference))
        #end
        ## Save the changes
        #set ($discard = $xwiki.xWiki.saveDocument($protectedDocument, "Replaced user [$oldUser] in fields $matchedFields to user [$newUser]", $xcontext.context))
       * [[doc:${prefixPage}$documentToUpdate[0]]] (${prefixPage}$documentToUpdate[0]) fields $matchedFields - (/)
      #end
      #if($hasSubWikis && $wikiId != $mainWikiId)
        #set($discard = $xcontext.setDatabase($currentWikiId))
      #end
    #end
   Done.

    {{html}}
   <a class='button' href="$doc.getURL()">Back to main screen</a>
    {{/html}}
  #else
   Documents to update ($docCount total) from [[doc:$oldUser]] ($oldUser) to [[doc:$newUserReference]] ($newUser) for fields $fields:
    #foreach($wikiId in $documentsPerWikiToUpdate.keySet())
      #set($documentsToUpdate = $documentsPerWikiToUpdate.get($wikiId))
      #set($prefix = "")
      #set($prefixUser = "")
      #if($hasSubWikis && $wikiId != $mainWikiId)
        #set($prefix = "${wikiId}:")
        #set($prefixUser = "${mainWikiId}:")
      #end
      #foreach ($documentToUpdate in $documentsToUpdate)
        #getMatchedFields($documentToUpdate "$prefixUser$oldUser")
       * [[${prefix}$documentToUpdate[0]]] (${prefix}$documentToUpdate[0]) fields $matchedFields
      #end
    #end

    {{html}}
   <form class='xform'>
     <dl>
       <dt>
         <input type='hidden' name='oldUser' value="$escapetool.xml($oldUser)" />
         <input type='hidden' name='newUser' value="$escapetool.xml($newUser)" />
          #foreach ($field in $fields)
           <input type='hidden' name='field' value="$escapetool.xml($field)" />
          #end
          #if($wantSubWikis)<input type='hidden' name='subwikis' value='y' />#end
         <input type='hidden' name='confirm' value='true' />
          #if ($docCount > 0)
           <input class='button' type='submit' value='Confirm' />
          #end
         <a class='button secondary' href="$doc.getURL()">Cancel</a>
       </dt>
     </dl>
   </form>
    {{/html}}
  #end
#else
 Replace all occurences of the old user with the new user for the selected fields of existing documents inside the current wiki.

 Based on the affected fields, this will also grant the affected documents the rights of the new user, instead of the old one's:
 * **contentAuthor**: Gives affected document Programming or Script rights, if the new user has them, allowing existing scripts or protected API calls inside that document to be executed when the document is viewed.
 * **author**: Gives affected document Admin or Programming rights, if the new user has them, allowing special objects (wiki macros, wiki components, UIX, translations) to be registered at a wiki or global level. Also updates the value displayed on the document's "Last modified by" section with the new user.
 * **creator**: Gives delete right for the document to the new user. Also updates the value displayed on the documents "Created by" section with the new user.

 The next step displays the list of documents that will be modified and will ask for confirmation.

 This page requires Programming Rights to function.

  {{html}}
 <form class='xform'>
   <dl>
     <dt><label>Old user to replace</label></dt>
      ## Can be existing or deleted user, so it makes sense to use a suggest widget.
     <dd><input class='suggestUsers' type='text' name='oldUser' #if ($oldUser != '')value="$escapetool.xml($oldUser)"#end /></dd>

     <dt><label>Fields to replace</label></dt>
     <dd>
       <label><input type='checkbox' name='field' value='author' #if (!$request.askConfirmation || $fields.contains('author'))checked="checked"#end />author</label><br/>
       <label><input type='checkbox' name='field' value='contentAuthor' #if (!$request.askConfirmation || $fields.contains('contentAuthor'))checked="checked"#end />contentAuthor</label><br/>
       <label><input type='checkbox' name='field' value='creator' #if ($fields.contains('creator'))checked="checked"#end />creator</label>
     </dd>

#if($hasSubWikis)
     <dt><label>Include Subwikis</label></dt>
     <dd>
       <label for='subwikis'><input type='checkbox' name='subwikis' id='subwikis' value='yes' #if ($wantSubWikis)checked="checked"#end />with subwikis</label>
     </dd>
#end
     <dt><label>New user to replace with</label></dt>
     <dd><input class='suggestUsers' type='text' name='newUser' #if ($newUser != '')value="$escapetool.xml($newUser)"#{else}value="$escapetool.xml(${xcontext.user})"#end /></dd>
   </dl>
   <div>
     <input type='submit' name='askConfirmation' class='button' value='Change...' />
   </div>
 </form>
  {{/html}}
#end
{{/velocity}}

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager). Note that installing Extensions when being offline is currently not supported and you'd need to use some complex manual method.

You can also use the following manual method, which is useful if this extension cannot be installed with the Extension Manager or if you're using an old version of XWiki that doesn't have the Extension Manager:

  1. Log in the wiki with a user having Administration rights
  2. Go to the Administration page and select the Import category
  3. Follow the on-screen instructions to upload the downloaded XAR
  4. Click on the uploaded XAR and follow the instructions
  5. You'll also need to install all dependent Extensions that are not already installed in your wiki

Release Notes

v2.2

Bugfix: the 2.1 version updated all selected author fields in a document, even if the original author was not the author t be replaces. 

v2.1

  • Allow to change the user in subwikis, too.

v2.0

  • Major refactoring
    • Added fields selector and updated the query
    • Updated the confirmation page to show the fields matched on each document that will be changed
    • Renamed page

v1.2

  • Fixed yet another bug when saving the document for which the contentAuthor field was changed.

v1.1

  • Fixed a bug in the published version when the document was saved.

Get Connected