Mercurial > moin > 1.9
view MoinMoin/_tests/test_user.py @ 6028:1893da1d5213
userid lookup caches: use 1 on-disk cache file, update cache rather than rebuild
Before this, we maintained one cache file per attribute (e.g. name2id, openid2id,
...) - the related code did multiple passes over all user profiles to rebuild these
cache files.
Now doing a one-pass rebuild, writing all attribute -> userid mappings into
one on-disk cache file called "lookup".
Additionally to "name" and "openids", support fast lookup for "email" and "jid" also.
On profile save, we use to just kill the cache and let it rebuild. Now the cache
is read, updated and written back (which is much less expensive for wikis with more
than a few users).
Did some refactoring also, reducing duplication, breaking down the code into smaller
functions / methods.
author | Thomas Waldmann <tw AT waldmann-edv DOT de> |
---|---|
date | Wed, 12 Feb 2014 18:22:10 +0100 |
parents | 05a6897ee496 |
children |
line wrap: on
line source
# -*- coding: utf-8 -*- """ MoinMoin - MoinMoin.user Tests @copyright: 2003-2004 by Juergen Hermann <jh@web.de> 2009 by ReimarBauer 2013 by MoinMoin:ThomasWaldmann @license: GNU GPL, see COPYING for details. """ import os import py from MoinMoin import user, caching class TestEncodePassword(object): """user: encode passwords tests""" def testAscii(self): """user: encode ascii password""" # u'MoinMoin' and 'MoinMoin' should be encoded to same result cfg = self.request.cfg tests = [ ('{PASSLIB}', '12345', "{PASSLIB}$6$rounds=1001$12345$jrPUCzPJt1yiixDbzIgSBoKED0/DlNDTHZN3lVarCtN6IM/.LoAw5pgUQH112CErU6wS8HXTZNpqb7wVjHLs/0"), ('{SSHA}', '12345', "{SSHA}xkDIIx1I7A4gC98Vt/+UelIkTDYxMjM0NQ=="), ] for scheme, salt, expected in tests: result = user.encodePassword(cfg, "MoinMoin", salt=salt, scheme=scheme) assert result == expected result = user.encodePassword(cfg, u"MoinMoin", salt=salt, scheme=scheme) assert result == expected def testUnicode(self): """ user: encode unicode password """ cfg = self.request.cfg tests = [ ('{PASSLIB}', '12345', "{PASSLIB}$6$rounds=1001$12345$5srFB66ZCu2JgGwPgdfb1lHRmqkjnKC/RxdsFlWn2WzoQh3btIjH6Ai1LJV9iYLDa9kLP/VQYa4DHLkRnaBw8."), ('{SSHA}', '12345', "{SSHA}YiwfeVWdVW9luqyVn8t2JivlzmUxMjM0NQ=="), ] for scheme, salt, expected in tests: result = user.encodePassword(cfg, u'סיסמה סודית בהחלט', salt=salt, scheme=scheme) # Hebrew assert result == expected class TestLoginWithPassword(object): """user: login tests""" def setup_method(self, method): # Save original user and cookie self.saved_cookie = self.request.cookies self.saved_user = self.request.user # Create anon user for the tests self.request.cookies = {} self.request.user = user.User(self.request) self.user = None self.passlib_support = self.request.cfg.passlib_support self.password_scheme = self.request.cfg.password_scheme def teardown_method(self, method): """ Run after each test Remove user and reset user listing cache. """ # Remove user file and user if self.user is not None: try: path = self.user._User__filename() os.remove(path) except OSError: pass del self.user # Restore original user self.request.cookies = self.saved_cookie self.request.user = self.saved_user # Remove user lookup caches, or next test will fail user.clearLookupCaches(self.request) def testAsciiPassword(self): """ user: login with ascii password """ # Create test user name = u'__Non Existent User Name__' password = name self.createUser(name, password) # Try to "login" theUser = user.User(self.request, name=name, password=password) assert theUser.valid def testUnicodePassword(self): """ user: login with non-ascii password """ # Create test user name = u'__שם משתמש לא קיים__' # Hebrew password = name self.createUser(name, password) # Try to "login" theUser = user.User(self.request, name=name, password=password) assert theUser.valid def test_auth_with_apr1_stored_password(self): """ Create user with {APR1} password and check that user can login. Also check if auto-upgrade happens and is saved to disk. """ # Create test user name = u'Test User' password = '12345' # generated with "htpasswd -nbm blaze 12345" pw_hash = '{APR1}$apr1$NG3VoiU5$PSpHT6tV0ZMKkSZ71E3qg.' self.createUser(name, pw_hash, True) # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) def test_auth_with_md5_stored_password(self): """ Create user with {MD5} password and check that user can login. Also check if auto-upgrade happens and is saved to disk. """ # Create test user name = u'Test User' password = '12345' pw_hash = '{MD5}$1$salt$etVYf53ma13QCiRbQOuRk/' self.createUser(name, pw_hash, True) # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) def test_auth_with_des_stored_password(self): """ Create user with {DES} password and check that user can login. Also check if auto-upgrade happens and is saved to disk. """ # Create test user name = u'Test User' password = '12345' # generated with "htpasswd -nbd blaze 12345" pw_hash = '{DES}gArsfn7O5Yqfo' self.createUser(name, pw_hash, True) try: import crypt # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) except ImportError: py.test.skip("Platform does not provide crypt module!") def test_auth_with_sha_stored_password(self): """ Create user with {SHA} password and check that user can login. Also check if auto-upgrade happens and is saved to disk. """ # Create test user name = u'Test User' password = '12345' pw_hash = '{SHA}jLIjfQZ5yojbZGTqxg2pY0VROWQ=' self.createUser(name, pw_hash, True) # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) def test_auth_with_ssha_stored_password(self): """ Create user with {SSHA} password and check that user can login. Also check if auto-upgrade happens and is saved to disk. """ # Create test user name = u'Test User' password = '12345' pw_hash = '{SSHA}dbeFtH5EGkOI1jgPADlGZgHWq072TIsKqWfHX7zZbUQa85Ze8774Rg==' self.createUser(name, pw_hash, True) # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) def test_auth_with_passlib_stored_password(self): """ Create user with {PASSLIB} password and check that user can login. """ if not self.passlib_support: py.test.skip("test requires passlib, but passlib_support is False") # Create test user name = u'Test User' password = '12345' pw_hash = '{PASSLIB}$6$rounds=1001$/AVWSh/RUWpcppfl$8DCRGLaBD3KoV4Ag67sUv6b2QdrUFXk1yWCxqWnBLJ.iHSe4Piv6nqzSQgELeLPIvwTC9APaWv1XCTOHjkLOj/' self.createUser(name, pw_hash, True) # Try to "login" theuser = user.User(self.request, name=name, password=password) assert theuser.valid # Check if the stored password was auto-upgraded on login and saved theuser = user.User(self.request, name=name, password=password) assert theuser.enc_password.startswith(self.password_scheme) def testSubscriptionSubscribedPage(self): """ user: tests isSubscribedTo """ pagename = u'HelpMiscellaneous' name = u'__Jürgen Herman__' password = name self.createUser(name, password) # Login - this should replace the old password in the user file theUser = user.User(self.request, name=name, password=password) theUser.subscribe(pagename) assert theUser.isSubscribedTo([pagename]) # list(!) of pages to check def testSubscriptionSubPage(self): """ user: tests isSubscribedTo on a subpage """ pagename = u'HelpMiscellaneous' testPagename = u'HelpMiscellaneous/FrequentlyAskedQuestions' name = u'__Jürgen Herman__' password = name self.createUser(name, password) # Login - this should replace the old password in the user file theUser = user.User(self.request, name=name, password=password) theUser.subscribe(pagename) assert not theUser.isSubscribedTo([testPagename]) # list(!) of pages to check def testRenameUser(self): """ create user and then rename user and check whether the old username is removed (and the lookup cache behaves well) """ # Create test user name = u'__Some Name__' password = name self.createUser(name, password) # Login - this should replace the old password in the user file theUser = user.User(self.request, name=name) # Rename user theUser.name = u'__SomeName__' theUser.save() theUser = user.User(self.request, name=name, password=password) assert not theUser.exists() def test_for_email_attribute_by_name(self): """ checks for no access to the email attribute by getting the user object from name """ name = u"__TestUser__" password = u"ekfdweurwerh" email = "__TestUser__@moinhost" self.createUser(name, password, email=email) theuser = user.User(self.request, name=name) assert theuser.email == "" def test_for_email_attribut_by_uid(self): """ checks access to the email attribute by getting the user object from the uid """ name = u"__TestUser2__" password = u"ekERErwerwerh" email = "__TestUser2__@moinhost" self.createUser(name, password, email=email) uid = user.getUserId(self.request, name) theuser = user.User(self.request, uid) assert theuser.email == email # Helpers --------------------------------------------------------- def createUser(self, name, password, pwencoded=False, email=None): """ helper to create test user """ # Create user self.user = user.User(self.request) self.user.name = name self.user.email = email if not pwencoded: password = user.encodePassword(self.request.cfg, password) self.user.enc_password = password # Validate that we are not modifying existing user data file! if self.user.exists(): self.user = None py.test.skip("Test user exists, will not override existing user data file!") # Save test user self.user.save() # Validate user creation if not self.user.exists(): self.user = None py.test.skip("Can't create test user") class TestGroupName(object): def testGroupNames(self): """ user: isValidName: reject group names """ test = u'AdminGroup' assert not user.isValidName(self.request, test) class TestIsValidName(object): def testNonAlnumCharacters(self): """ user: isValidName: reject unicode non alpha numeric characters : and , used in acl rules, we might add more characters to the syntax. """ invalid = u'! # $ % ^ & * ( ) = + , : ; " | ~ / \\ \u0000 \u202a'.split() base = u'User%sName' for c in invalid: name = base % c assert not user.isValidName(self.request, name) def testWhitespace(self): """ user: isValidName: reject leading, trailing or multiple whitespace """ cases = ( u' User Name', u'User Name ', u'User Name', ) for test in cases: assert not user.isValidName(self.request, test) def testValid(self): """ user: isValidName: accept names in any language, with spaces """ cases = ( u'Jürgen Hermann', # German u'ניר סופר', # Hebrew u'CamelCase', # Good old camel case u'가각간갇갈 갉갊감 갬갯걀갼' # Hangul (gibberish) ) for test in cases: assert user.isValidName(self.request, test) coverage_modules = ['MoinMoin.user']