diff options
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 2 | ||||
| -rw-r--r-- | src/mailman/rest/addresses.py | 13 | ||||
| -rw-r--r-- | src/mailman/rest/tests/test_addresses.py | 43 |
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. |
