changeset 1286:d2704c2a8d39 namespaces

meta NAME and User.name is always a list of unicode names add a User.name0 property that returns name[0] (or "anonymous") TODO: permissions check still uses only user.name0
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 04 Mar 2012 01:30:58 +0100
parents ca1c015c2e43
children 90df744feb6b
files MoinMoin/_tests/__init__.py MoinMoin/_tests/test_user.py MoinMoin/auth/_tests/test_auth.py MoinMoin/auth/_tests/test_http.py MoinMoin/auth/_tests/test_log.py MoinMoin/config/default.py MoinMoin/constants/keys.py MoinMoin/datastruct/backends/_tests/test_wiki_groups.py MoinMoin/security/__init__.py MoinMoin/storage/middleware/_tests/test_indexing.py MoinMoin/storage/middleware/_tests/test_protecting.py MoinMoin/storage/middleware/_tests/test_routing.py MoinMoin/storage/middleware/indexing.py MoinMoin/storage/middleware/protecting.py MoinMoin/storage/middleware/validation.py MoinMoin/themes/__init__.py MoinMoin/user.py
diffstat 17 files changed, 102 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/__init__.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/_tests/__init__.py	Sun Mar 04 01:30:58 2012 +0100
@@ -33,8 +33,8 @@
         Thus, for testing purposes (e.g. if you need delete rights), it is
         easier to use become_trusted().
     """
-    flaskg.user.profile[NAME] = username
-    flaskg.user.may.name = username
+    flaskg.user.profile[NAME] = [username, ]
+    flaskg.user.may.name = username # currently just one/first name, see security.Permissions class
     flaskg.user.valid = 1
 
 
@@ -53,7 +53,7 @@
     item = flaskg.storage[name]
 
     if NAME not in meta:
-        meta[NAME] = [name]
+        meta[NAME] = [name, ]
     if CONTENTTYPE not in meta:
         meta[CONTENTTYPE] = u'application/octet-stream'
     rev = item.store_revision(meta, StringIO(data))
--- a/MoinMoin/_tests/test_user.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/_tests/test_user.py	Sun Mar 04 01:30:58 2012 +0100
@@ -24,7 +24,7 @@
         email = u"foo@example.org"
         # nonexisting user
         u = user.User(name=name, password=password)
-        assert u.name == name
+        assert u.name == [name, ]
         assert not u.valid
         assert not u.exists()
         # create a user
@@ -32,7 +32,7 @@
         assert ret is None, "create_user returned: {0}".format(ret)
         # existing user
         u = user.User(name=name, password=password)
-        assert u.name == [name]
+        assert u.name == [name, ]
         assert u.email == email
         assert u.valid
         assert u.exists()
--- a/MoinMoin/auth/_tests/test_auth.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/auth/_tests/test_auth.py	Sun Mar 04 01:30:58 2012 +0100
@@ -20,7 +20,7 @@
         auth = [GivenAuth(user_name=u'JoeDoe', autocreate=True), ]
 
     def test(self):
-        assert flaskg.user.name == u'JoeDoe'
+        assert flaskg.user.name == [u'JoeDoe', ]
 
 
 class TestGivenAuth(object):
@@ -52,7 +52,7 @@
         create_user(u'Test_User', u'test_pass', u'test@moinmoin.org')
         test_user, bool_value = givenauth_obj.request(flaskg.user)
         assert test_user.valid
-        assert test_user.name == [u'Test_User']
+        assert test_user.name == [u'Test_User', ]
 
 def test_handle_login():
     # no messages in the beginning
@@ -60,7 +60,7 @@
     test_user1 = handle_login(flaskg.user, login_username = 'test_user', login_password = 'test_password', stage = 'moin')
     test_login_message = [u'Invalid username or password.']
     assert flaskg._login_messages == test_login_message
-    assert test_user1.name == u'anonymous'
+    assert test_user1.name0 == u'anonymous'
     assert not test_user1.valid
     # pop the message
     flaskg._login_messages.pop()
@@ -72,7 +72,7 @@
     test_user, bool_value = givenauth_obj.request(flaskg.user)
     test_user2 = handle_login(test_user, login_username = 'Test_User', login_password = 'test_pass', stage = 'moin')
     assert not flaskg._login_messages
-    assert test_user2.name == [u'Test_User']
+    assert test_user2.name == [u'Test_User', ]
     assert test_user2.valid
 
 def test_get_multistage_continuation_url():
--- a/MoinMoin/auth/_tests/test_http.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/auth/_tests/test_http.py	Sun Mar 04 01:30:58 2012 +0100
@@ -33,12 +33,12 @@
         httpauthmoin_obj = HTTPAuthMoin()
         test_user, bool_val = httpauthmoin_obj.request(flaskg.user)
         assert test_user.valid
-        assert test_user.name == [u'ValidUser']
+        assert test_user.name == [u'ValidUser', ]
         assert bool_val
 
         # when auth_method is not 'http'
         flaskg.user.auth_method = 'invalid'
         test_user, bool_val = httpauthmoin_obj.request(flaskg.user)
         assert not test_user.valid
-        assert test_user.name == u'anonymous'
+        assert test_user.name0 == u'anonymous'
 
--- a/MoinMoin/auth/_tests/test_log.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/auth/_tests/test_log.py	Sun Mar 04 01:30:58 2012 +0100
@@ -19,13 +19,13 @@
         result = authlog_obj.login(flaskg.user)
         assert result.continue_flag
         test_user_obj = result.user_obj
-        assert test_user_obj.name == u'anonymous'
+        assert test_user_obj.name0 == u'anonymous'
 
     def test_request(self):
         authlog_obj = AuthLog()
         result = authlog_obj.request(flaskg.user)
         test_user, bool_value = result
-        assert test_user.name == u'anonymous'
+        assert test_user.name0 == u'anonymous'
         assert not test_user.valid
         assert bool_value
 
@@ -33,7 +33,7 @@
         authlog_obj = AuthLog()
         result = authlog_obj.logout(flaskg.user)
         test_user, bool_value = result
-        assert test_user.name == u'anonymous'
+        assert test_user.name0 == u'anonymous'
         assert not test_user.valid
         assert bool_value
 
--- a/MoinMoin/config/default.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/config/default.py	Sun Mar 04 01:30:58 2012 +0100
@@ -443,7 +443,7 @@
   'user': ('User Preferences related', None, (
     ('user_defaults',
       dict(
-        name=u'anonymous',
+        name=[],
         display_name=None,
         email=None,
         openid=None,
--- a/MoinMoin/constants/keys.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/constants/keys.py	Sun Mar 04 01:30:58 2012 +0100
@@ -63,7 +63,7 @@
 # stuff from user profiles / for whoosh index
 EMAIL = "email"
 OPENID = "openid"
-ALIASNAME = "aliasname"
+DISPLAY_NAME = "display_name"
 THEME_NAME = "theme_name"
 LOCALE = "locale"
 TIMEZONE = "timezone"
--- a/MoinMoin/datastruct/backends/_tests/test_wiki_groups.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/datastruct/backends/_tests/test_wiki_groups.py	Sun Mar 04 01:30:58 2012 +0100
@@ -44,7 +44,7 @@
         assert u'ExampleUser' in flaskg.groups[u'SomeGroup']
         pytest.raises(GroupDoesNotExistError, lambda: flaskg.groups[u'AnotherGroup'])
 
-        item = update_item(u'SomeGroup', {NAME: u'AnotherGroup', USERGROUP: ["ExampleUser"]}, DATA)
+        item = update_item(u'SomeGroup', {NAME: [u'AnotherGroup', ], USERGROUP: ["ExampleUser"]}, DATA)
         assert u'ExampleUser' in flaskg.groups[u'AnotherGroup']
         pytest.raises(GroupDoesNotExistError, lambda: flaskg.groups[u'SomeGroup'])
 
--- a/MoinMoin/security/__init__.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/security/__init__.py	Sun Mar 04 01:30:58 2012 +0100
@@ -66,7 +66,7 @@
             return Permissions.read(itemname)
     """
     def __init__(self, user):
-        self.name = user.name
+        self.name = user.name0 # XXX currently we just use first name
 
     def __getattr__(self, attr):
         """ Shortcut to handle all known ACL rights.
--- a/MoinMoin/storage/middleware/_tests/test_indexing.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/_tests/test_indexing.py	Sun Mar 04 01:30:58 2012 +0100
@@ -54,7 +54,7 @@
         item_name = u'foo'
         data = 'bar'
         item = self.imw[item_name]
-        rev = item.store_revision(dict(name=item_name), StringIO(data))
+        rev = item.store_revision(dict(name=[item_name, ]), StringIO(data))
         revid = rev.revid
         # check if we have the revision now:
         item = self.imw[item_name]
@@ -70,10 +70,10 @@
         data = 'bar'
         newdata = 'baz'
         item = self.imw[item_name]
-        rev = item.store_revision(dict(name=item_name, comment=u'spam'), StringIO(data))
+        rev = item.store_revision(dict(name=[item_name, ], comment=u'spam'), StringIO(data))
         revid = rev.revid
         # clear revision:
-        item.store_revision(dict(name=item_name, revid=revid, comment=u'no spam'), StringIO(newdata), overwrite=True)
+        item.store_revision(dict(name=[item_name, ], revid=revid, comment=u'no spam'), StringIO(newdata), overwrite=True)
         # check if the revision was overwritten:
         item = self.imw[item_name]
         rev = item.get_revision(revid)
@@ -87,13 +87,13 @@
     def test_destroy_revision(self):
         item_name = u'foo'
         item = self.imw[item_name]
-        rev = item.store_revision(dict(name=item_name, mtime=1),
+        rev = item.store_revision(dict(name=[item_name, ], mtime=1),
                                   StringIO('bar'), trusted=True)
         revid0 = rev.revid
-        rev = item.store_revision(dict(name=item_name, mtime=2),
+        rev = item.store_revision(dict(name=[item_name, ], mtime=2),
                                   StringIO('baz'), trusted=True)
         revid1 = rev.revid
-        rev = item.store_revision(dict(name=item_name, mtime=3),
+        rev = item.store_revision(dict(name=[item_name, ], mtime=3),
                                   StringIO('...'), trusted=True)
         revid2 = rev.revid
         print "revids:", revid0, revid1, revid2
@@ -129,10 +129,10 @@
         revids = []
         item_name = u'foo'
         item = self.imw[item_name]
-        rev = item.store_revision(dict(name=item_name, mtime=1),
+        rev = item.store_revision(dict(name=[item_name, ], mtime=1),
                                   StringIO('bar'), trusted=True)
         revids.append(rev.revid)
-        rev = item.store_revision(dict(name=item_name, mtime=2),
+        rev = item.store_revision(dict(name=[item_name, ], mtime=2),
                                   StringIO('baz'), trusted=True)
         revids.append(rev.revid)
         # destroy item:
@@ -144,11 +144,11 @@
     def test_all_revisions(self):
         item_name = u'foo'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name), StringIO('does not count, different name'))
+        item.store_revision(dict(name=[item_name, ]), StringIO('does not count, different name'))
         item_name = u'bar'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name), StringIO('1st'))
-        item.store_revision(dict(name=item_name), StringIO('2nd'))
+        item.store_revision(dict(name=[item_name, ]), StringIO('1st'))
+        item.store_revision(dict(name=[item_name, ]), StringIO('2nd'))
         item = self.imw[item_name]
         revs = [rev.data.read() for rev in item.iter_revs()]
         assert len(revs) == 2
@@ -157,11 +157,11 @@
     def test_latest_revision(self):
         item_name = u'foo'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name), StringIO('does not count, different name'))
+        item.store_revision(dict(name=[item_name, ]), StringIO('does not count, different name'))
         item_name = u'bar'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name), StringIO('1st'))
-        expected_rev = item.store_revision(dict(name=item_name), StringIO('2nd'))
+        item.store_revision(dict(name=[item_name, ]), StringIO('1st'))
+        expected_rev = item.store_revision(dict(name=[item_name, ]), StringIO('2nd'))
         revs = list(self.imw.documents(name=item_name))
         assert len(revs) == 1  # there is only 1 latest revision
         assert expected_rev.revid == revs[0].revid  # it is really the latest one
@@ -170,7 +170,7 @@
         item_name = u'foo'
         data = 'bar'
         item = self.imw[item_name]
-        rev = item.store_revision(dict(name=item_name), StringIO(data))
+        rev = item.store_revision(dict(name=[item_name, ]), StringIO(data))
         print repr(rev.meta)
         assert rev.name == item_name
         assert rev.meta[SIZE] == len(data)
@@ -182,9 +182,9 @@
     def test_documents(self):
         item_name = u'foo'
         item = self.imw[item_name]
-        rev1 = item.store_revision(dict(name=item_name), StringIO('x'))
-        rev2 = item.store_revision(dict(name=item_name), StringIO('xx'))
-        rev3 = item.store_revision(dict(name=item_name), StringIO('xxx'))
+        rev1 = item.store_revision(dict(name=[item_name, ]), StringIO('x'))
+        rev2 = item.store_revision(dict(name=[item_name, ]), StringIO('xx'))
+        rev3 = item.store_revision(dict(name=[item_name, ]), StringIO('xxx'))
         rev = self.imw.document(idx_name=ALL_REVS, size=2)
         assert rev
         assert rev.revid == rev2.revid
@@ -197,14 +197,14 @@
         expected_latest_revids = []
         item_name = u'foo'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=1),
+        r = item.store_revision(dict(name=[item_name, ], mtime=1),
                                 StringIO('does not count, different name'), trusted=True)
         expected_latest_revids.append(r.revid)
         item_name = u'bar'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name, mtime=1),
+        item.store_revision(dict(name=[item_name, ], mtime=1),
                             StringIO('1st'), trusted=True)
-        r = item.store_revision(dict(name=item_name, mtime=2),
+        r = item.store_revision(dict(name=[item_name, ], mtime=2),
                                 StringIO('2nd'), trusted=True)
         expected_latest_revids.append(r.revid)
 
@@ -246,24 +246,24 @@
         missing_revids = []
         item_name = u'updated'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=1),
+        r = item.store_revision(dict(name=[item_name, ], mtime=1),
                                 StringIO('updated 1st'), trusted=True)
         expected_all_revids.append(r.revid)
         # we update this item below, so we don't add it to expected_latest_revids
         item_name = u'destroyed'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=1),
+        r = item.store_revision(dict(name=[item_name, ], mtime=1),
                                 StringIO('destroyed 1st'), trusted=True)
         destroy_revid = r.revid
         # we destroy this item below, so we don't add it to expected_all_revids
         # we destroy this item below, so we don't add it to expected_latest_revids
         item_name = u'stayssame'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=1),
+        r = item.store_revision(dict(name=[item_name, ], mtime=1),
                                 StringIO('stayssame 1st'), trusted=True)
         expected_all_revids.append(r.revid)
         # we update this item below, so we don't add it to expected_latest_revids
-        r = item.store_revision(dict(name=item_name, mtime=2),
+        r = item.store_revision(dict(name=[item_name, ], mtime=2),
                                 StringIO('stayssame 2nd'), trusted=True)
         expected_all_revids.append(r.revid)
         expected_latest_revids.append(r.revid)
@@ -279,14 +279,14 @@
         # this will not change the fresh index, but the old index we are still using.
         item_name = u'updated'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=2),
+        r = item.store_revision(dict(name=[item_name, ], mtime=2),
                                 StringIO('updated 2nd'), trusted=True)
         expected_all_revids.append(r.revid)
         expected_latest_revids.append(r.revid)
         missing_revids.append(r.revid)
         item_name = u'added'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, mtime=1),
+        r = item.store_revision(dict(name=[item_name, ], mtime=1),
                                 StringIO('added 1st'), trusted=True)
         expected_all_revids.append(r.revid)
         expected_latest_revids.append(r.revid)
@@ -334,7 +334,7 @@
     def test_revision_contextmanager(self):
         # check if rev.data is closed after leaving the with-block
         item_name = u'foo'
-        meta = dict(name=item_name)
+        meta = dict(name=[item_name, ])
         data = 'some test content'
         item = self.imw[item_name]
         data_file = StringIO(data)
@@ -353,7 +353,7 @@
         # TODO: this is a very simple check that assumes that data is put 1:1
         # into index' CONTENT field.
         item_name = u'foo'
-        meta = dict(name=item_name, contenttype=u'text/plain')
+        meta = dict(name=[item_name, ], contenttype=u'text/plain')
         data = 'some test content\n'
         item = self.imw[item_name]
         data_file = StringIO(data)
@@ -367,14 +367,14 @@
     def test_namespaces(self):
         item_name_n = u'normal'
         item = self.imw[item_name_n]
-        rev_n = item.store_revision(dict(name=[item_name_n], contenttype=u'text/plain'), StringIO(str(item_name_n)))
+        rev_n = item.store_revision(dict(name=[item_name_n, ], contenttype=u'text/plain'), StringIO(str(item_name_n)))
         item_name_u = u'userprofiles:userprofile'
         item = self.imw[item_name_u]
-        rev_u = item.store_revision(dict(name=[item_name_u], contenttype=u'text/plain'), StringIO(str(item_name_u)))
+        rev_u = item.store_revision(dict(name=[item_name_u, ], contenttype=u'text/plain'), StringIO(str(item_name_u)))
         item = self.imw[item_name_n]
         rev_n = item.get_revision(rev_n.revid)
         assert rev_n.meta[NAMESPACE] == u''
-        assert rev_n.meta[NAME] == [item_name_n]
+        assert rev_n.meta[NAME] == [item_name_n, ]
         item = self.imw[item_name_u]
         rev_u = item.get_revision(rev_u.revid)
         assert rev_u.meta[NAMESPACE] == u'userprofiles'
@@ -395,7 +395,7 @@
     def test_documents(self):
         item_name = u'public'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, acl=u'joe:read'), StringIO('public content'))
+        r = item.store_revision(dict(name=[item_name, ], acl=u'joe:read'), StringIO('public content'))
         revid_public = r.revid
         revids = [rev.revid for rev in self.imw.documents()
                   if rev.name != u'joe'] # the user profile is a revision in the backend
@@ -404,7 +404,7 @@
     def test_getitem(self):
         item_name = u'public'
         item = self.imw[item_name]
-        r = item.store_revision(dict(name=item_name, acl=u'joe:read'), StringIO('public content'))
+        r = item.store_revision(dict(name=[item_name, ], acl=u'joe:read'), StringIO('public content'))
         revid_public = r.revid
         # now testing:
         item_name = u'public'
@@ -419,7 +419,7 @@
         item_name = u'foo'
         item = self.imw[item_name]
         for i in xrange(100):
-            item.store_revision(dict(name=item_name, acl=u'joe:create joe:read'), StringIO('some content'))
+            item.store_revision(dict(name=[item_name, ], acl=u'joe:create joe:read'), StringIO('some content'))
 
     def test_perf_create_read(self):
         pytest.skip("usually we do no performance tests")
@@ -429,7 +429,7 @@
         item_name = u'foo'
         item = self.imw[item_name]
         for i in xrange(100):
-            item.store_revision(dict(name=item_name, acl=u'joe:create joe:read'), StringIO('rev number {0}'.format(i)))
+            item.store_revision(dict(name=[item_name, ], acl=u'joe:create joe:read'), StringIO('rev number {0}'.format(i)))
         for r in item.iter_revs():
             #print r.meta
             #print r.data.read()
--- a/MoinMoin/storage/middleware/_tests/test_protecting.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/_tests/test_protecting.py	Sun Mar 04 01:30:58 2012 +0100
@@ -28,17 +28,21 @@
     ('', dict(before=u'', default=u'All:read,write,create', after=u'', hierarchic=False)),
 ]
 
-class User(object):
+class FakeUser(object):
     """
     fake user object, just to give user.name
     """
     def __init__(self, name):
-        self.name = name
+        self.name = [name, ]
+    @property
+    def name0(self):
+        return self.name[0]
+
 
 class TestProtectingMiddleware(TestIndexingMiddleware):
     def setup_method(self, method):
         super(TestProtectingMiddleware, self).setup_method(method)
-        self.imw = ProtectingMiddleware(self.imw, User(u'joe'), acl_mapping=acl_mapping)
+        self.imw = ProtectingMiddleware(self.imw, FakeUser(u'joe'), acl_mapping=acl_mapping)
 
     def teardown_method(self, method):
         self.imw = self.imw.indexer
@@ -59,7 +63,7 @@
         revids = []
         for item_name, acl, content in items:
             item = self.imw[item_name]
-            r = item.store_revision(dict(name=item_name, acl=acl, contenttype=u'text/plain'),
+            r = item.store_revision(dict(name=[item_name, ], acl=acl, contenttype=u'text/plain'),
                                     StringIO(content))
             revids.append(r.revid)
         return revids
@@ -83,26 +87,26 @@
         revid_unprotected, revid_protected = self.make_items(u'joe:write', u'boss:write')
         # now testing:
         item = self.imw[UNPROTECTED]
-        item.store_revision(dict(name=UNPROTECTED, acl=u'joe:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
+        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
         item = self.imw[PROTECTED]
         with pytest.raises(AccessDenied):
-            item.store_revision(dict(name=PROTECTED, acl=u'boss:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
+            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
 
     def test_write_create(self):
         # now testing:
         item_name = u'newitem'
         item = self.imw[item_name]
-        item.store_revision(dict(name=item_name, contenttype=u'text/plain'), StringIO('new content'))
+        item.store_revision(dict(name=[item_name, ], contenttype=u'text/plain'), StringIO('new content'))
 
     def test_overwrite_revision(self):
         revid_unprotected, revid_protected = self.make_items(u'joe:write,destroy', u'boss:write,destroy')
         # now testing:
         item = self.imw[UNPROTECTED]
-        item.store_revision(dict(name=UNPROTECTED, acl=u'joe:write,destroy', contenttype=u'text/plain', revid=revid_unprotected),
+        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write,destroy', contenttype=u'text/plain', revid=revid_unprotected),
                             StringIO(UNPROTECTED_CONTENT), overwrite=True)
         item = self.imw[PROTECTED]
         with pytest.raises(AccessDenied):
-            item.store_revision(dict(name=PROTECTED, acl=u'boss:write,destroy', contenttype=u'text/plain', revid=revid_protected),
+            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write,destroy', contenttype=u'text/plain', revid=revid_protected),
                                 StringIO(UNPROTECTED_CONTENT), overwrite=True)
 
     def test_destroy_revision(self):
--- a/MoinMoin/storage/middleware/_tests/test_routing.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/_tests/test_routing.py	Sun Mar 04 01:30:58 2012 +0100
@@ -50,15 +50,17 @@
 
 def test_store_get_del(router):
     default_name = u'foo'
-    default_backend_name, default_revid = router.store(dict(name=default_name), StringIO(''))
+    default_backend_name, default_revid = router.store(dict(name=[default_name, ]), StringIO(''))
     other_name = u'other:bar'
-    other_backend_name, other_revid = router.store(dict(name=other_name), StringIO(''))
+    other_backend_name, other_revid = router.store(dict(name=[other_name, ]), StringIO(''))
 
     # check if store() updates the to-store metadata with correct NAMESPACE and NAME
     default_meta, _ = router.retrieve(default_backend_name, default_revid)
     other_meta, _ = router.retrieve(other_backend_name, other_revid)
-    assert (u'', default_name == default_meta[NAMESPACE], default_meta[NAME])
-    assert (other_name.split(':') == other_meta[NAMESPACE], other_meta[NAME])
+    assert u'' == default_meta[NAMESPACE]
+    assert [default_name, ] == default_meta[NAME]
+    assert other_name.split(':')[0] == other_meta[NAMESPACE]
+    assert other_name.split(':')[1] == other_meta[NAME][0]
 
     # delete revs:
     router.remove(default_backend_name, default_revid)
@@ -67,7 +69,7 @@
 
 def test_store_readonly_fails(router):
     with pytest.raises(TypeError):
-        router.store(dict(name=u'ro:testing'), StringIO(''))
+        router.store(dict(name=[u'ro:testing', ]), StringIO(''))
 
 def test_del_readonly_fails(router):
     ro_be_name, ro_id = next(iter(router)) # we have only readonly items
@@ -78,8 +80,8 @@
 
 def test_destroy_create_dont_touch_ro(router):
     existing = set(router)
-    default_be_name, default_revid = router.store(dict(name=u'foo'), StringIO(''))
-    other_be_name, other_revid = router.store(dict(name=u'other:bar'), StringIO(''))
+    default_be_name, default_revid = router.store(dict(name=[u'foo', ]), StringIO(''))
+    other_be_name, other_revid = router.store(dict(name=[u'other:bar', ]), StringIO(''))
 
     router.close()
     router.destroy()
@@ -91,8 +93,8 @@
 
 def test_iter(router):
     existing_before = set([revid for be_name, revid in router])
-    default_be_name, default_revid = router.store(dict(name=u'foo'), StringIO(''))
-    other_be_name, other_revid = router.store(dict(name=u'other:bar'), StringIO(''))
+    default_be_name, default_revid = router.store(dict(name=[u'foo', ]), StringIO(''))
+    other_be_name, other_revid = router.store(dict(name=[u'other:bar', ]), StringIO(''))
     existing_now = set([revid for be_name, revid in router])
     assert existing_now == set([default_revid, other_revid]) | existing_before
 
--- a/MoinMoin/storage/middleware/indexing.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/indexing.py	Sun Mar 04 01:30:58 2012 +0100
@@ -922,7 +922,7 @@
         # just update the meta dict with the validated stuff:
         meta.update(dict(m.value.items()))
         # we do not want None / empty values:
-        meta = dict([(k, v) for k, v in meta.items() if v not in [None, []]])
+        meta = dict([(k, v) for k, v in meta.items() if v not in [None, ]]) # do not kick out empty lists before fixing NAME processing
 
         if self.itemid is None:
             self.itemid = meta[ITEMID]
--- a/MoinMoin/storage/middleware/protecting.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/protecting.py	Sun Mar 04 01:30:58 2012 +0100
@@ -208,7 +208,7 @@
         :returns: True if you have permission or False
         """
         if user_name is None:
-            user_name = self.protector.user.name
+            user_name = self.protector.user.name0
 
         acl_cfg = self.protector._get_configured_acls(self.item.fqname)
         full_acl = self.full_acl()
@@ -221,7 +221,7 @@
 
     def require(self, capability):
         if not self.allows(capability):
-            raise AccessDenied("item does not allow user '{0!r}' to '{1!r}'".format(self.protector.user.name, capability))
+            raise AccessDenied("item does not allow user '{0!r}' to '{1!r}'".format(self.protector.user.name0, capability))
 
     def iter_revs(self):
         self.require(READ)
--- a/MoinMoin/storage/middleware/validation.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/storage/middleware/validation.py	Sun Mar 04 01:30:58 2012 +0100
@@ -320,7 +320,7 @@
     String.named(keys.WIKINAME).using(strip=False).validated_by(wikiname_validator),
     String.named(keys.NAMESPACE).using(strip=False).validated_by(namespace_validator),
     List.named(keys.NAME).of(String.using(strip=False).validated_by(name_validator)),
-    String.named(keys.NAME_OLD).using(strip=False).validated_by(name_validator).using(optional=True),
+    List.named(keys.NAME_OLD).of(String.using(strip=False).validated_by(name_validator)).using(optional=True),
     Integer.named(keys.MTIME).validated_by(mtime_validator),
     String.named(keys.ACTION).validated_by(action_validator),
     String.named(keys.ACL).validated_by(acl_validator),
--- a/MoinMoin/themes/__init__.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/themes/__init__.py	Sun Mar 04 01:30:58 2012 +0100
@@ -139,7 +139,7 @@
         :returns: arguments of user homepage link in tuple (wiki_href, display_name, title, exists)
         """
         user = self.user
-        name = user.name
+        name = user.name0
         display_name = user.display_name or name
         wikiname, itemname = getInterwikiHome(name)
         title = "{0} @ {1}".format(display_name, wikiname)
@@ -307,7 +307,7 @@
     userid = meta.get(USERID)
     if userid:
         u = user.User(userid)
-        name = u.name[0]
+        name = u.name0
         text = name
         display_name = u.display_name or name
         if title:
--- a/MoinMoin/user.py	Sat Mar 03 22:09:16 2012 +0100
+++ b/MoinMoin/user.py	Sun Mar 04 01:30:58 2012 +0100
@@ -59,7 +59,8 @@
     if validate and search_users(name_exact=username):
         return _("This user name already belongs to somebody else.")
 
-    theuser.profile[NAME] = unicode(username)
+    # XXX currently we just support creating with 1 name:
+    theuser.profile[NAME] = [unicode(username), ]
 
     pw_checker = app.cfg.password_checker
     if validate and pw_checker:
@@ -139,7 +140,7 @@
         if userdata.mailto_author and userdata.email:
             return ('email', userdata.email)
         elif userdata.name:
-            interwiki = getInterwikiHome(userdata.name)
+            interwiki = getInterwikiHome(userdata.name0)
             if interwiki:
                 result = ('interwiki', interwiki)
     return result
@@ -275,6 +276,7 @@
         self.auth_method = kw.get('auth_method', 'internal')
         self.auth_attribs = kw.get('auth_attribs', ())
 
+        # XXX currently we just support creating with 1 name:
         _name = name or auth_username
 
         itemid = uid
@@ -291,7 +293,7 @@
         else:
             self.profile[ITEMID] = make_uuid()
             if _name:
-                self.profile[NAME] = _name
+                self.profile[NAME] = [_name, ]
             if password is not None:
                 self.set_password(password)
 
@@ -305,13 +307,13 @@
     def __repr__(self):
         return "<{0}.{1} at {2:#x} name:{3!r} itemid:{4!r} valid:{5!r} trusted:{6!r}>".format(
             self.__class__.__module__, self.__class__.__name__, id(self),
-            self.name, self.itemid, self.valid, self.trusted)
+            self.name0, self.itemid, self.valid, self.trusted)
 
     def __getattr__(self, name):
         """
         delegate some lookups into the .profile
         """
-        if name in [NAME, DISABLED, ITEMID, ALIASNAME, ENC_PASSWORD, EMAIL, OPENID,
+        if name in [NAME, DISABLED, ITEMID, DISPLAY_NAME, ENC_PASSWORD, EMAIL, OPENID,
                     MAILTO_AUTHOR, SHOW_COMMENTS, RESULTS_PER_PAGE, EDIT_ON_DOUBLECLICK,
                     THEME_NAME, LOCALE, TIMEZONE, SUBSCRIBED_ITEMS, QUICKLINKS,
                    ]:
@@ -320,6 +322,15 @@
             raise AttributeError(name)
 
     @property
+    def name0(self):
+        try:
+            names = self.name
+            assert isinstance(names, list)
+            return names[0]
+        except IndexError:
+            return u'anonymous'
+
+    @property
     def language(self):
         l = self._cfg.language_default
         locale = self.locale  # is either None or something like 'en_US'
@@ -687,7 +698,7 @@
 If you didn't forget your password, please ignore this email.
 
 """, link=url_for('frontend.recoverpass',
-                        username=self.name, token=token, _external=True))
+                        username=self.name0, token=token, _external=True))
 
         subject = _('[%(sitename)s] Your wiki password recovery link',
                     sitename=self._cfg.sitename or "Wiki")
@@ -708,7 +719,7 @@
 If you didn't create this account, please ignore this email.
 
 """, link=url_for('frontend.verifyemail',
-                        username=self.name, token=token, _external=True))
+                        username=self.name0, token=token, _external=True))
 
         subject = _('[%(sitename)s] Please verify your email address',
                     sitename=self._cfg.sitename or "Wiki")