Barry Warsaw pushed to branch master at mailman / Mailman
Commits: d1954d17 by Mark Sapiro at 2016-10-20T17:44:25-07:00 First cut at PUT/PATCH for domain. - - - - - cbb0847d by Mark Sapiro at 2016-10-22T12:24:00-07:00 Merge gitlab.com:mailman/mailman - - - - - 2e1bc9aa by Mark Sapiro at 2016-10-22T17:33:07-07:00 Fixed a bunch of things in PATCHing domains and added tests and NEWS. - - - - - 3a198afc by Mark Sapiro at 2016-10-22T18:18:16-07:00 Merge gitlab.com:mailman/mailman - - - - - 7c8b75fd by Mark Sapiro at 2016-10-23T18:37:07-07:00 Modify NEWS.rst entry to mention PUT. - - - - - 3 changed files: - src/mailman/docs/NEWS.rst - src/mailman/rest/domains.py - src/mailman/rest/tests/test_domains.py Changes: ===================================== src/mailman/docs/NEWS.rst ===================================== --- 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 PUT and PATCH domain attributes. Allows Postorius domain + edit to work. (Closes: #290) Configuration ------------- ===================================== src/mailman/rest/domains.py ===================================== --- 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""" ===================================== src/mailman/rest/tests/test_domains.py ===================================== --- 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': 'a...@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], + ['a...@example.com']) + + def test_patch_domain_two_owners(self): + # Patch the example.com owner. + data = {'owner': ['a...@example.com', 'ot...@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], + ['a...@example.com', 'ot...@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( View it on GitLab: https://gitlab.com/mailman/mailman/compare/4cd3c3f309bb91d46a7ce55a32216db2321804c1...7c8b75fd1ab364871274397509cd6ce314197138
_______________________________________________ Mailman-checkins mailing list Mailman-checkins@python.org Unsubscribe: https://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org