diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 2 | ||||
| -rw-r--r-- | src/mailman/rest/domains.py | 32 | ||||
| -rw-r--r-- | src/mailman/rest/tests/test_domains.py | 50 |
3 files changed, 81 insertions, 3 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 7f4acc5c4..919a1ef5a 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -91,6 +91,8 @@ Bugs * Allow MailingList.info to be set using the REST API. Given by Aurélien Bompard. * Extend header filters to also check sub-part headers. (Closes #280) + * Allow REST API to PATCH some domain attributes. Enables Postorius domain + edit to work. (Closes: #290) Configuration ------------- diff --git a/src/mailman/rest/domains.py b/src/mailman/rest/domains.py index 7f54e8905..c6b8daa7c 100644 --- a/src/mailman/rest/domains.py +++ b/src/mailman/rest/domains.py @@ -21,11 +21,11 @@ from mailman import public from mailman.interfaces.domain import ( BadDomainSpecificationError, IDomainManager) from mailman.rest.helpers import ( - BadRequest, CollectionMixin, NotFound, bad_request, child, created, etag, - no_content, not_found, okay) + BadRequest, CollectionMixin, GetterSetter, NotFound, bad_request, child, + created, etag, no_content, not_found, okay) from mailman.rest.lists import ListsForDomain from mailman.rest.uris import ADomainURI, AllDomainURIs -from mailman.rest.users import OwnersForDomain +from mailman.rest.users import ListOfDomainOwners, OwnersForDomain from mailman.rest.validator import Validator, list_of_strings_validator from zope.component import getUtility @@ -71,6 +71,32 @@ class ADomain(_DomainBase): else: no_content(response) + def patch_put(self, request, response, is_optional): + domain = getUtility(IDomainManager).get(self._domain) + if domain is None: + not_found(response) + kws = dict( + description=GetterSetter(str), + owner=ListOfDomainOwners(list_of_strings_validator), + ) + if is_optional: + # For a PATCH, all attributes are optional. + kws['_optional'] = kws.keys() + try: + Validator(**kws).update(domain, request) + except ValueError as error: + bad_request(response, str(error)) + else: + no_content(response) + + def on_put(self, request, response): + """Update all the domain except mail_host""" + self.patch_put(request, response, is_optional=False) + + def on_patch(self, request, response): + """Patch some domain attributes.""" + self.patch_put(request, response, is_optional=True) + @child() def lists(self, context, segments): """/domains/<domain>/lists""" diff --git a/src/mailman/rest/tests/test_domains.py b/src/mailman/rest/tests/test_domains.py index c707eaadb..5daa1ccf7 100644 --- a/src/mailman/rest/tests/test_domains.py +++ b/src/mailman/rest/tests/test_domains.py @@ -48,6 +48,56 @@ class TestDomains(unittest.TestCase): 'http://localhost:9001/3.0/domains', data, method="POST") self.assertEqual(response.status, 201) + def test_patch_domain_description(self): + # Patch the example.com description. + data = {'description': 'Patched example domain'} + content, response = call_api( + 'http://localhost:9001/3.0/domains/example.com', + data, + method='PATCH') + self.assertEqual(response.status, 204) + # Check the result. + domain = getUtility(IDomainManager).get('example.com') + self.assertEqual(domain.description, 'Patched example domain') + + def test_patch_domain_owner(self): + # Patch the example.com owner. + data = {'owner': 'anne@example.com'} + content, response = call_api( + 'http://localhost:9001/3.0/domains/example.com', + data, + method='PATCH') + self.assertEqual(response.status, 204) + # Check the result. + domain = getUtility(IDomainManager).get('example.com') + self.assertEqual( + [list(owner.addresses)[0].email for owner in domain.owners], + ['anne@example.com']) + + def test_patch_domain_two_owners(self): + # Patch the example.com owner. + data = {'owner': ['anne@example.com', 'other@example.net']} + content, response = call_api( + 'http://localhost:9001/3.0/domains/example.com', + data, + method='PATCH') + self.assertEqual(response.status, 204) + # Check the result. + domain = getUtility(IDomainManager).get('example.com') + self.assertEqual( + [list(owner.addresses)[0].email for owner in domain.owners], + ['anne@example.com', 'other@example.net']) + + def test_patch_domain_readonly(self): + # Attempt to patch mail_host. + data = {'mail_host': 'example.net'} + with self.assertRaises(HTTPError) as cm: + call_api( + 'http://localhost:9001/3.0/domains/example.com', + data, + method='PATCH') + self.assertEqual(cm.exception.code, 400) + def test_domain_create_with_single_owner(self): # Creating domain with single owner should not raise InvalidEmailError. content, response = call_api( |
