summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/docs/NEWS.rst2
-rw-r--r--src/mailman/rest/addresses.py13
-rw-r--r--src/mailman/rest/tests/test_addresses.py43
3 files changed, 55 insertions, 3 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index edc8a0f96..b813e5b65 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -57,6 +57,8 @@ REST
Bompard.
* The REST API incorrectly parsed `is_server_owner` values when given
explicitly in the POST that creates a user. (Closes #136)
+ * By POSTing to a user resource with an existing unlinked address, you can
+ link the address to the user. Given by Abhilash Raj.
Other
-----
diff --git a/src/mailman/rest/addresses.py b/src/mailman/rest/addresses.py
index 9dbbf3fc8..2bc13e1cc 100644
--- a/src/mailman/rest/addresses.py
+++ b/src/mailman/rest/addresses.py
@@ -211,11 +211,20 @@ class UserAddresses(_AddressBase):
except InvalidEmailAddressError:
bad_request(response, b'Invalid email address')
except ExistingAddressError:
- bad_request(response, b'Address already exists')
+ # Check if the address is not linked to any user, link it to the
+ # current user and return it. Since we're linking to an existing
+ # address, ignore any given display_name attribute.
+ address = user_manager.get_address(validator(request)['email'])
+ if address.user is None:
+ address.user = self._user
+ location = self.path_to('addresses/{}'.format(address.email))
+ created(response, location)
+ else:
+ bad_request(response, 'Address belongs to other user.')
else:
# Link the address to the current user and return it.
address.user = self._user
- location = self.path_to('addresses/{0}'.format(address.email))
+ location = self.path_to('addresses/{}'.format(address.email))
created(response, location)
diff --git a/src/mailman/rest/tests/test_addresses.py b/src/mailman/rest/tests/test_addresses.py
index d03dc79d7..152ce4aa5 100644
--- a/src/mailman/rest/tests/test_addresses.py
+++ b/src/mailman/rest/tests/test_addresses.py
@@ -168,7 +168,48 @@ class TestAddresses(unittest.TestCase):
'email': 'anne@example.com',
})
self.assertEqual(cm.exception.code, 400)
- self.assertEqual(cm.exception.reason, b'Address already exists')
+ self.assertEqual(cm.exception.reason,
+ b'Address belongs to other user.')
+
+ def test_add_unlinked_address_to_user(self):
+ user_manager = getUtility(IUserManager)
+ with transaction():
+ anne = user_manager.create_user('anne.person@example.com')
+ user_manager.create_address('anne@example.com')
+ response, content = call_api(
+ 'http://localhost:9001/3.0/users/anne.person@example.com/addresses', {
+ 'email': 'anne@example.com',
+ })
+ self.assertIn('anne@example.com',
+ [address.email for address in anne.addresses])
+ self.assertEqual(content['status'], '201')
+ self.assertEqual(
+ content['location'],
+ 'http://localhost:9001/3.0/addresses/anne@example.com')
+ # The address has no display name.
+ anne_person = user_manager.get_address('anne@example.com')
+ self.assertEqual(anne_person.display_name, '')
+
+ def test_add_unlinked_address_to_user_with_ignored_display_name(self):
+ user_manager = getUtility(IUserManager)
+ with transaction():
+ anne = user_manager.create_user('anne.person@example.com')
+ user_manager.create_address('anne@example.com')
+ response, content = call_api(
+ 'http://localhost:9001/3.0/users/anne.person@example.com/addresses', {
+ 'email': 'anne@example.com',
+ 'display_name': 'Anne Person',
+ })
+ self.assertIn('anne@example.com',
+ [address.email for address in anne.addresses])
+ self.assertEqual(content['status'], '201')
+ self.assertEqual(
+ content['location'],
+ 'http://localhost:9001/3.0/addresses/anne@example.com')
+ # Even though a display_name was given in the POST data, because the
+ # address already existed, it still has no display name.
+ anne_person = user_manager.get_address('anne@example.com')
+ self.assertEqual(anne_person.display_name, '')
def test_invalid_address_bad_request(self):
# Trying to add an invalid address string returns 400.