diff options
Diffstat (limited to 'src/mailman/rest/tests/test_users.py')
| -rw-r--r-- | src/mailman/rest/tests/test_users.py | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/src/mailman/rest/tests/test_users.py b/src/mailman/rest/tests/test_users.py index 805baf67e..ae9b8130e 100644 --- a/src/mailman/rest/tests/test_users.py +++ b/src/mailman/rest/tests/test_users.py @@ -21,20 +21,23 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ - 'TestUsers', 'TestLP1074374', + 'TestLogin', + 'TestUsers', ] +import os import unittest from urllib2 import HTTPError from zope.component import getUtility from mailman.app.lifecycle import create_list +from mailman.config import config from mailman.database.transaction import transaction from mailman.interfaces.usermanager import IUserManager -from mailman.testing.helpers import call_api +from mailman.testing.helpers import call_api, configuration from mailman.testing.layers import RESTLayer @@ -131,6 +134,22 @@ class TestUsers(unittest.TestCase): call_api('http://localhost:9001/3.0/users/z@example.net/addresses') self.assertEqual(cm.exception.code, 404) + def test_login_missing_user_by_id(self): + # Verify a password for a non-existing user, by id. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/users/99/login', { + 'cleartext_password': 'wrong', + }) + self.assertEqual(cm.exception.code, 404) + + def test_login_missing_user_by_address(self): + # Verify a password for a non-existing user, by address. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/users/z@example.org/login', { + 'cleartext_password': 'wrong', + }) + self.assertEqual(cm.exception.code, 404) + class TestLP1074374(unittest.TestCase): @@ -214,3 +233,67 @@ class TestLP1074374(unittest.TestCase): self.assertEqual(member['delivery_mode'], 'regular') self.assertEqual(member['list_id'], 'test.example.com') self.assertEqual(member['role'], 'member') + + + +class TestLogin(unittest.TestCase): + """Test user 'login' (really just password verification).""" + + layer = RESTLayer + + def setUp(self): + user_manager = getUtility(IUserManager) + with transaction(): + self.anne = user_manager.create_user( + 'anne@example.com', 'Anne Person') + self.anne.password = config.password_context.encrypt('abc123') + + def test_wrong_parameter(self): + # A bad request because it is mistyped the required attribute. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/users/1/login', { + 'hashed_password': 'bad hash', + }) + self.assertEqual(cm.exception.code, 400) + + def test_not_enough_parameters(self): + # A bad request because it is missing the required attribute. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/users/1/login', { + }) + self.assertEqual(cm.exception.code, 400) + + def test_too_many_parameters(self): + # A bad request because it has too many attributes. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/users/1/login', { + 'cleartext_password': 'abc123', + 'display_name': 'Annie Personhood', + }) + self.assertEqual(cm.exception.code, 400) + + def test_successful_login_updates_password(self): + # Passlib supports updating the hash when the hash algorithm changes. + # When a user logs in successfully, the password will be updated if + # necessary. + # + # Start by hashing Anne's password with a different hashing algorithm + # than the one that the REST runner uses by default during testing. + config_file = os.path.join(config.VAR_DIR, 'passlib-tmp.config') + with open(config_file, 'w') as fp: + print("""\ +[passlib] +schemes = hex_md5 +""", file=fp) + with configuration('passwords', configuration=config_file): + with transaction(): + self.anne.password = config.password_context.encrypt('abc123') + # Just ensure Anne's password is hashed correctly. + self.assertEqual(self.anne.password, + 'e99a18c428cb38d5f260853678922e03') + # Now, Anne logs in with a successful password. This should change it + # back to the plaintext hash. + call_api('http://localhost:9001/3.0/users/1/login', { + 'cleartext_password': 'abc123', + }) + self.assertEqual(self.anne.password, '{plaintext}abc123') |
