diff options
Diffstat (limited to 'src/mailman/rest')
| -rw-r--r-- | src/mailman/rest/addresses.py | 26 | ||||
| -rw-r--r-- | src/mailman/rest/tests/test_addresses.py | 19 |
2 files changed, 39 insertions, 6 deletions
diff --git a/src/mailman/rest/addresses.py b/src/mailman/rest/addresses.py index 4624db379..8fc6871b5 100644 --- a/src/mailman/rest/addresses.py +++ b/src/mailman/rest/addresses.py @@ -192,30 +192,44 @@ class UserAddresses(_AddressBase): user_manager = getUtility(IUserManager) validator = Validator(email=str, display_name=str, - _optional=('display_name',)) + force_existing=bool, + _optional=('display_name', 'force_existing')) try: - address = user_manager.create_address(**validator(request)) + data = validator(request) except ValueError as error: bad_request(response, str(error)) + return + force_existing = data.pop('force_existing', False) + try: + address = user_manager.create_address(**data) except InvalidEmailAddressError: bad_request(response, b'Invalid email address') + return except ExistingAddressError: # 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']) + address = user_manager.get_address(data['email']) if address.user is None: address.user = self._user location = self.api.path_to( 'addresses/{}'.format(address.email)) created(response, location) + return else: - bad_request(response, 'Address belongs to other user.') + if not force_existing: + bad_request(response, 'Address belongs to other user.') + return + else: + # The address exists and is linked but we can merge the + # users. + address = user_manager.get_address(data['email']) + self._user.absorb(address.user) else: # Link the address to the current user and return it. address.user = self._user - location = self.api.path_to('addresses/{}'.format(address.email)) - created(response, location) + location = self.api.path_to('addresses/{}'.format(address.email)) + created(response, location) def membership_key(member): diff --git a/src/mailman/rest/tests/test_addresses.py b/src/mailman/rest/tests/test_addresses.py index edcfdfa86..c75641ea9 100644 --- a/src/mailman/rest/tests/test_addresses.py +++ b/src/mailman/rest/tests/test_addresses.py @@ -212,6 +212,25 @@ class TestAddresses(unittest.TestCase): anne_person = user_manager.get_address('anne@example.com') self.assertEqual(anne_person.display_name, '') + def test_existing_address_absorb(self): + # Trying to add an existing address causes a merge if the + # 'force_existing' flag is present. + user_manager = getUtility(IUserManager) + with transaction(): + anne = user_manager.create_user('anne@example.com') + bill = user_manager.create_user('bill@example.com') + response, content = call_api( + 'http://localhost:9001/3.0/users/anne@example.com/addresses', { + 'email': 'bill@example.com', + 'force_existing': '1', + }) + self.assertIn('bill@example.com', + [addr.email for addr in anne.addresses]) + self.assertEqual(content['status'], '201') + self.assertEqual( + content['location'], + 'http://localhost:9001/3.0/addresses/bill@example.com') + def test_invalid_address_bad_request(self): # Trying to add an invalid address string returns 400. with transaction(): |
