# HG changeset patch
# User Paul Boddie <paul@boddie.org.uk>
# Date 1318182665 -7200
# Node ID 0f57c22a22e960d3df5df6374fe9b4d202ab4c06
# Parent  8d94ac6b5587a8b7946148f24f93003648679d5f
Added support for home page namespaces other than at the root of a site by
employing a homeprefix setting.
Changed the serveopenid action, autoadmin security policy, MyPages action and
the OpenID identity advertising in the Page class to work with home pages that
have a non-empty homeprefix.
Added various utility functions to work with page names.
Handle a result of None, possible when running a maintenance script or when no
user is logged in.
(Consolidated patch from 4530, 4536 and 4538.)

diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/Page.py
--- a/MoinMoin/Page.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/Page.py	Sun Oct 09 19:51:05 2011 +0200
@@ -1138,8 +1138,14 @@
 
                 html_head = ''
                 if request.cfg.openid_server_enabled:
-                    openid_username = self.page_name
-                    userid = user.getUserId(request, openid_username)
+                    pagenames = wikiutil.splitPageName(self.page_name)
+                    prefix = wikiutil.joinPageNames(*pagenames[:-1])
+                    if prefix == request.cfg.user_homeprefix:
+                        openid_username = pagenames[-1]
+                        userid = user.getUserId(request, openid_username)
+                    else:
+                        openid_username = None
+                        userid = None
 
                     if userid is None and 'openid.user' in self.pi:
                         openid_username = self.pi['openid.user']
@@ -1375,7 +1381,11 @@
         _ = request.getText
 
         if special_type == 'missing':
-            if request.user.valid and request.user.name == self.page_name and \
+            pagenames = wikiutil.splitPageName(self.page_name)
+            prefix = wikiutil.joinPageNames(*pagenames[:-1])
+
+            if request.user.valid and request.user.name == pagenames[-1] and \
+               request.cfg.user_homeprefix == prefix and \
                request.cfg.user_homewiki in ('Self', request.cfg.interwikiname):
                 page = wikiutil.getLocalizedPage(request, 'MissingHomePage')
             else:
diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/action/MyPages.py
--- a/MoinMoin/action/MyPages.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/action/MyPages.py	Sun Oct 09 19:51:05 2011 +0200
@@ -30,7 +30,7 @@
         homepageurl = wikiutil.join_wiki(wikiurl, wikitail)
         request.http_redirect('%s?action=MyPages' % homepageurl)
 
-    homepage = Page(request, username)
+    homepage = Page(request, wikiutil.joinPageNames(request.cfg.user_homeprefix, username))
     if not homepage.exists():
         request.theme.add_msg(_('Please first create a homepage before creating additional pages.'), "error")
         return homepage.send_page()
diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/action/serveopenid.py
--- a/MoinMoin/action/serveopenid.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/action/serveopenid.py	Sun Oct 09 19:51:05 2011 +0200
@@ -175,7 +175,13 @@
         request = self.request
         form = request.form
 
-        username = request.page.page_name
+        pagenames = wikiutil.splitPageName(request.page.page_name)
+        prefix = wikiutil.joinPageNames(*pagenames[:-1])
+        if prefix == request.cfg.user_homeprefix:
+            username = pagenames[-1]
+        else:
+            username = None
+
         if 'openid.user' in request.page.pi:
             username = request.page.pi['openid.user']
 
diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/config/multiconfig.py
--- a/MoinMoin/config/multiconfig.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/config/multiconfig.py	Sun Oct 09 19:51:05 2011 +0200
@@ -1117,6 +1117,8 @@
 
       ('homewiki', u'Self',
        "interwiki name of the wiki where the user home pages are located [Unicode] - useful if you have ''many'' users. You could even link to nonwiki \"user pages\" if the wiki username is in the target URL."),
+      ('homeprefix', u'',
+       "name of the page under which user home pages are stored [Unicode] - this page can itself be a subpage of another page; set to the empty string for the normal top-level home page behaviour."),
 
       ('checkbox_fields',
        [
diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/security/autoadmin.py
--- a/MoinMoin/security/autoadmin.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/security/autoadmin.py	Sun Oct 09 19:51:05 2011 +0200
@@ -62,6 +62,7 @@
 from MoinMoin.security import Permissions
 from MoinMoin.Page import Page
 from MoinMoin.PageEditor import PageEditor
+from MoinMoin import wikiutil
 
 class SecurityPolicy(Permissions):
     """ Extend the default security policy with autoadmin feature """
@@ -72,9 +73,20 @@
             has_member = request.dicts.has_member
             username = request.user.name
             pagename = request.page.page_name
+
+            # test admin rights on the user's own home page
+            homedetails = wikiutil.getInterwikiHomePage(request, username)
+
+            if homedetails is not None:
+                homewiki, homepage = homedetails
+
+                if homewiki == "Self" and \
+                   (pagename == homepage or wikiutil.isSubPage(pagename, homepage)) and \
+                   has_member('AutoAdminGroup', username):
+                    return True
+
+            # test admin rights for the user on group pages
             mainpage = pagename.split('/')[0]
-            if username == mainpage and has_member('AutoAdminGroup', username):
-                return True
             groupname = "%s/AdminGroup" % mainpage
             if has_member(groupname, username) and has_member('AutoAdminGroup', groupname):
                 return True
@@ -86,19 +98,23 @@
         request = self.request
         username = request.user.name
         pagename = editor.page_name
+        homedetails = wikiutil.getInterwikiHomePage(request, username)
 
-        if grouppage_autocreate and username == pagename:
-            # create group pages when a user saves his own homepage
-            for page in grouppages:
-                grouppagename = "%s/%s" % (username, page)
-                grouppage = Page(request, grouppagename)
-                if not grouppage.exists():
-                    text = """\
+        if homedetails is not None:
+            homewiki, homepage = homedetails
+
+            if grouppage_autocreate and homewiki == "Self" and pagename == homepage:
+                # create group pages when a user saves his own homepage
+                for page in grouppages:
+                    grouppagename = "%s/%s" % (homepage, page)
+                    grouppage = Page(request, grouppagename)
+                    if not grouppage.exists():
+                        text = """\
 #acl %(username)s:read,write,delete,revert
  * %(username)s
 """ % locals()
-                    editor = PageEditor(request, grouppagename)
-                    editor._write_file(text)
+                        editor = PageEditor(request, grouppagename)
+                        editor._write_file(text)
 
         parts = pagename.split('/')
         if len(parts) == 2:
diff -r 8d94ac6b5587 -r 0f57c22a22e9 MoinMoin/wikiutil.py
--- a/MoinMoin/wikiutil.py	Sat Mar 26 20:57:11 2011 +0100
+++ b/MoinMoin/wikiutil.py	Sun Oct 09 19:51:05 2011 +0200
@@ -811,7 +811,7 @@
     # known user?
     if username:
         # Return home page
-        page = Page(request, username)
+        page = Page(request, joinPageNames(request.cfg.user_homeprefix, username))
         if page.exists():
             return page
 
@@ -843,8 +843,40 @@
     if homewiki == request.cfg.interwikiname:
         homewiki = u'Self'
 
-    return homewiki, username
+    return homewiki, joinPageNames(request.cfg.user_homeprefix, username)
 
+def joinPageNames(*pagenames):
+    """
+    Join the given page names to construct a complete absolute page name.
+
+    @param pagenames: the page names which construct the complete name
+    @return: the absolute page name
+    """
+
+    pagenames = [name for name in pagenames if name]
+    return u'/'.join(pagenames)
+
+def splitPageName(pagename):
+    """
+    Split the given page name into a hierarchy of pages.
+
+    @param pagename: an absolute page name with potentially many parts
+    @return: a list of page names
+    """
+
+    return pagename.split(u'/')
+
+def isSubPage(pagename, parent):
+    """
+    Return whether the given page name is a subpage of the potential parent
+    page.
+
+    @param pagename: a page name to be tested as a potential subpage
+    @param parent: a potential parent page
+    @return: a boolean value indicating whether pagename is a subpage of parent
+    """
+
+    return pagename.startswith("%s/" % parent)
 
 def AbsPageName(context, pagename):
     """
