Introduction / Context

At work, I administer a small Moin instance for tech-savvy people. It's only accessible on the intranet and the Wiki is closed to only let authorized people to access the information.

As this wiki instance also contains documentation which can be interesting for other people, the idea was to open the wiki to accept other users, but still controlling to which information they can access, as some needs to be only accessible by the original group of users.

As the script used and the information about the methodology can be useful for other people, I share it here.

If you want to correct some mistakes, ask questions or simply discuss about this, please use the /Discussion page.

Details

The initial configuration is similar to:

The ACL specified in wikiconfig.py are like

acl_rights_before = u"AdminsGroup:read,write,revert,delete,admin"
acl_rights_default = u"ReadersGroup:read All:"

Security is also enforced by using LDAP authentication, restricting access to a specific usergroup in the LDAP directory.

Problems

The normal use of a Wiki is to be open to all users, even anonymous one. This way content can be 'protected' with this behaviour in mind, using ACL on pages or some hierarchy of pages.

As our decision was to use our wiki in a non-common way, ie. closing it completely, opening it later giving different access to some content is non-natural and complicated.

After a lot of reflexions and tests, one solution was choosen and will be presented below, but FYI here is a short list of some of the other solutions that were imagined and finally not adopted (with the problems associated):

Solution

The solution that we finally choose and implement is the following:

Script

Steps 1 (pages rename) and 2 (update links) were handled by a script to avoid excessive repetition of human tasks and errors. This script is presented here and commented below. I hope it can be useful for other people.

   1 #!/usr/bin/python
   2 # -*- coding: utf-8 -*-
   3 
   4 import os, re, shutil, sys
   5 from MoinMoin.Page import Page
   6 from MoinMoin.PageEditor import PageEditor
   7 from MoinMoin.web.contexts import ScriptContext
   8 
   9 
  10 ## variables
  11 wiki_dir = "/var/www/wikiinstance"
  12 wiki_url = "http://wiki.domain.tld"
  13 
  14 renaming_prefix = "SomeHierarchy/"
  15 
  16 immutables_pages_regex = ur"""
  17         ^(\S+)Category$
  18         |
  19         ^(\S+)Dict$
  20         |
  21         ^(\S+)Group$
  22         |
  23         ^(\S+)Template$
  24         |
  25         ^
  26         (
  27          [a-z-]+
  28          \.
  29          [a-z-]+
  30          (\/.+)*
  31         )
  32         |^(\S*)Hierarchy$
  33         |^ToDo$
  34         |^SomeSpecificPage$
  35         """
  36 
  37 
  38 ##
  39 def classify_pages():
  40     """
  41     function to classify pages depending of their type
  42     - immutables pages of if they are underlay or match the immutables_pages_regex
  43     - invalid pages if they don't exists
  44     - valid pages for others
  45     """
  46     regex = re.compile(immutables_pages_regex, re.VERBOSE)
  47     request = ScriptContext(wiki_url)
  48     pagelist = request.rootpage.getPageList(include_underlay=False)
  49     for pagename in pagelist:
  50         try:
  51             page = Page(request, pagename)
  52         except: 
  53             print 'exception'
  54             continue
  55         if not page.exists:
  56             invalid_pages.append(pagename)
  57         if page.isUnderlayPage() or regex.search(pagename):
  58             immutables_pages.append(pagename)
  59         else:
  60             valid_pages.append(pagename)
  61 
  62 
  63 def renaming_pages(pages, prefix):
  64     """
  65     Renaming pages with the moin API
  66     
  67     @param pages: list of pages to rename
  68     @param prefix: prefix used to rename pages
  69     """
  70     request = ScriptContext(wiki_url)
  71     for pagename in pages:
  72         try:
  73             page = PageEditor(request, pagename)        
  74         except:
  75             print "exception on %s" % pagename
  76             continue
  77         page.renamePage(prefix+pagename)
  78 
  79 
  80 def update_links(changed_pages, prefix):
  81     """
  82     Verify all pages to change any links in the changed_pages list
  83     to add the defined prefix
  84 
  85     @param pages: list of pages renamed
  86     @param prefix: prefix used to update links
  87     """
  88     request = ScriptContext(wiki_url)
  89     pagelist = request.rootpage.getPageList(include_underlay=False)
  90     for pagename in pagelist:
  91         try:
  92             page = PageEditor(request, pagename)
  93         except:
  94             print "exception on %s" % pagename
  95             continue
  96         links = page.getPageLinks(request)
  97         to_be_changed_links = []
  98         not_changed_links = []
  99         text = page.get_raw_body()
 100         for link in links:
 101             if link in changed_pages:
 102                 to_be_changed_links.append(link)
 103                 text = text.replace(link, prefix+link)
 104             else:
 105                 not_changed_links.append(link)
 106         try:
 107             page.saveText(text, 0, comments="updated links")
 108         except (PageEditor.Unchanged, PageEditor.EmptyPage):
 109             continue
 110 
 111 
 112 if __name__ == "__main__":
 113     sys.path.append(wiki_dir)
 114     import wikiconfig
 115     wikiconfig.Config.acl_rights_before = wikiconfig.Config.acl_rights_before + " All:read,write,delete,revert,admin"
 116 
 117     invalid_pages = []
 118     immutables_pages = []
 119     valid_pages = []
 120 
 121     classify_pages()
 122 
 123     renaming_pages(valid_pages, renaming_prefix)
 124 
 125     update_links(valid_pages, renaming_prefix) 

The variables (lines 11 to 35) needs to be edited to suit to your configuration.

The immutables_pages_regex lets you define which pages will not be renamed. In the example there are:

Changes are handled with the moin api so they appears in the RecentChanges page, but as 'anonymous'.

Links

MoinMoin: EricVeirasGalisson/MoinScripting-MovingALotOfPagesToAnotherHierarchy (last edited 2010-09-13 12:53:25 by EricVeirasGalisson)