summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2015-05-10 22:13:14 +0000
committerBarry Warsaw2015-05-10 22:13:14 +0000
commitd6e93bd29f06f0b4d73e455c0170ee1616a17e21 (patch)
treeb8aa13d329c16a0f97903d7072a99699537dd093
parente214f22aeac9d037518e4de3440248c509ed14cb (diff)
parentfe57f807c0cfa36949fb8287e345002fc90948fd (diff)
downloadmailman-d6e93bd29f06f0b4d73e455c0170ee1616a17e21.tar.gz
mailman-d6e93bd29f06f0b4d73e455c0170ee1616a17e21.tar.zst
mailman-d6e93bd29f06f0b4d73e455c0170ee1616a17e21.zip
-rw-r--r--src/mailman/docs/NEWS.rst6
-rw-r--r--src/mailman/rest/docs/users.rst32
-rw-r--r--src/mailman/rest/tests/test_users.py37
-rw-r--r--src/mailman/rest/users.py19
4 files changed, 88 insertions, 6 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 95663d5ee..0000afb73 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -22,6 +22,12 @@ Configuration
* The default languages from Mailman 2.1 have been ported over. Given by
Aurélien Bompard.
+REST
+----
+ * When creating a user via REST using an address that already exists, but
+ isn't linked, the address is linked to the new user. Given by Aurélien
+ Bompard.
+
3.0.0 -- "Show Don't Tell"
==========================
diff --git a/src/mailman/rest/docs/users.rst b/src/mailman/rest/docs/users.rst
index 13390a00f..493cf65e2 100644
--- a/src/mailman/rest/docs/users.rst
+++ b/src/mailman/rest/docs/users.rst
@@ -496,3 +496,35 @@ Gwen, a new users, takes over as a server owner.
password: {plaintext}...
self_link: http://localhost:9001/3.0/users/7
user_id: 7
+
+
+Linking users
+=============
+
+If an address already exists, but is not yet linked to a user, and a new user
+is requested for that address, the user will be linked to the existing
+address.
+
+Herb's address already exists, but no user is linked to it.
+
+ >>> herb = user_manager.create_address('herb@example.com')
+ >>> print(herb.user)
+ None
+ >>> transaction.commit()
+
+Now, a user creation request is received, using Herb's email address.
+
+ >>> dump_json('http://localhost:9001/3.0/users', {
+ ... 'email': 'herb@example.com',
+ ... 'display_name': 'Herb Person',
+ ... })
+ content-length: 0
+ date: ...
+ location: http://localhost:9001/3.0/users/8
+ server: ...
+ status: 201
+
+Herb's email address is now linked to the new user.
+
+ >>> herb.user
+ <User "Herb Person" (8) at ...
diff --git a/src/mailman/rest/tests/test_users.py b/src/mailman/rest/tests/test_users.py
index ac8d018e8..d58d7f9c3 100644
--- a/src/mailman/rest/tests/test_users.py
+++ b/src/mailman/rest/tests/test_users.py
@@ -160,7 +160,7 @@ class TestUsers(unittest.TestCase):
})
self.assertEqual(cm.exception.code, 400)
self.assertEqual(cm.exception.reason,
- b'Address already exists: anne@example.com')
+ b'User already exists: anne@example.com')
def test_addresses_of_missing_user_id(self):
# Trying to get the /addresses of a missing user id results in error.
@@ -190,6 +190,39 @@ class TestUsers(unittest.TestCase):
})
self.assertEqual(cm.exception.code, 404)
+ def test_existing_address_link(self):
+ # Creating a user with an existing address links them.
+ user_manager = getUtility(IUserManager)
+ with transaction():
+ user_manager.create_address('anne@example.com')
+ call_api('http://localhost:9001/3.0/users', dict(
+ email='anne@example.com',
+ ))
+ anne = user_manager.get_user('anne@example.com')
+ self.assertEqual(anne.display_name, '')
+ self.assertFalse(anne.is_server_owner)
+ self.assertIn('anne@example.com',
+ [address.email for address in anne.addresses])
+
+ def test_existing_address_link_with_arguments(self):
+ # Creating a user with an existing address links them, and the
+ # addition arguments get honored.
+ user_manager = getUtility(IUserManager)
+ with transaction():
+ user_manager.create_address('anne@example.com')
+ call_api('http://localhost:9001/3.0/users', dict(
+ email='anne@example.com',
+ display_name='Anne Person',
+ password='123',
+ is_server_owner=True,
+ ))
+ anne = user_manager.get_user('anne@example.com')
+ self.assertEqual(anne.display_name, 'Anne Person')
+ self.assertTrue(anne.is_server_owner)
+ self.assertEqual(anne.password, '{plaintext}123')
+ self.assertIn('anne@example.com',
+ [address.email for address in anne.addresses])
+
def test_create_user_twice(self):
# LP: #1418280. No additional users should be created when an address
# that already exists is given.
@@ -207,7 +240,7 @@ class TestUsers(unittest.TestCase):
email='anne@example.com'))
self.assertEqual(cm.exception.code, 400)
self.assertEqual(cm.exception.reason,
- b'Address already exists: anne@example.com')
+ b'User already exists: anne@example.com')
# But at least no new users was created.
content, response = call_api('http://localhost:9001/3.0/users')
self.assertEqual(content['total_size'], 1)
diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py
index 7b1ec8040..4521593d4 100644
--- a/src/mailman/rest/users.py
+++ b/src/mailman/rest/users.py
@@ -96,12 +96,23 @@ def create_user(arguments, response):
# after the fact if successful.
password = arguments.pop('password', None)
is_server_owner = arguments.pop('is_server_owner', False)
+ user_manager = getUtility(IUserManager)
try:
- user = getUtility(IUserManager).create_user(**arguments)
+ user = user_manager.create_user(**arguments)
except ExistingAddressError as error:
- bad_request(
- response, 'Address already exists: {}'.format(error.address))
- return None
+ # The address already exists. If the address already has a user
+ # linked to it, raise an error, otherwise create a new user and link
+ # it to this address.
+ email = arguments.pop('email')
+ user = user_manager.get_user(email)
+ if user is None:
+ address = user_manager.get_address(email)
+ user = user_manager.create_user(**arguments)
+ user.link(address)
+ else:
+ bad_request(
+ response, 'User already exists: {}'.format(error.address))
+ return None
if password is None:
# This will have to be reset since it cannot be retrieved.
password = generate(int(config.passwords.password_length))