diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/rest/addresses.py | 37 | ||||
| -rw-r--r-- | src/mailman/rest/configuration.py | 41 | ||||
| -rw-r--r-- | src/mailman/rest/domains.py | 28 | ||||
| -rw-r--r-- | src/mailman/rest/helpers.py | 46 | ||||
| -rw-r--r-- | src/mailman/rest/lists.py | 46 | ||||
| -rw-r--r-- | src/mailman/rest/members.py | 53 | ||||
| -rw-r--r-- | src/mailman/rest/moderation.py | 46 | ||||
| -rw-r--r-- | src/mailman/rest/preferences.py | 18 | ||||
| -rw-r--r-- | src/mailman/rest/root.py | 6 | ||||
| -rw-r--r-- | src/mailman/rest/templates.py | 7 | ||||
| -rw-r--r-- | src/mailman/rest/users.py | 67 | ||||
| -rw-r--r-- | src/mailman/rest/wsgiapp.py | 10 |
12 files changed, 190 insertions, 215 deletions
diff --git a/src/mailman/rest/addresses.py b/src/mailman/rest/addresses.py index a1ed31781..475f0699d 100644 --- a/src/mailman/rest/addresses.py +++ b/src/mailman/rest/addresses.py @@ -27,8 +27,6 @@ __all__ = [ ] -import falcon - from operator import attrgetter from zope.component import getUtility @@ -36,7 +34,8 @@ from mailman.interfaces.address import ( ExistingAddressError, InvalidEmailAddressError) from mailman.interfaces.usermanager import IUserManager from mailman.rest.helpers import ( - BadRequest, CollectionMixin, NotFound, child, etag, path_to) + BadRequest, CollectionMixin, NotFound, bad_request, child, created, etag, + no_content, not_found, okay, path_to) from mailman.rest.members import MemberCollection from mailman.rest.preferences import Preferences from mailman.rest.validator import Validator @@ -77,8 +76,7 @@ class AllAddresses(_AddressBase): def on_get(self, request, response): """/addresses""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @@ -96,7 +94,7 @@ class _VerifyResource: self._address.verified_on = now() elif self._action == 'unverify': self._address.verified_on = None - response.status = falcon.HTTP_204 + no_content(response) class AnAddress(_AddressBase): @@ -113,11 +111,9 @@ class AnAddress(_AddressBase): def on_get(self, request, response): """Return a single address.""" if self._address is None: - falcon.responders.path_not_found( - request, response, b'404 Not Found') + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = self._resource_as_json(self._address) + okay(response, self._resource_as_json(self._address)) @child() def memberships(self, request, segments): @@ -177,12 +173,9 @@ class UserAddresses(_AddressBase): def on_get(self, request, response): """/addresses""" if self._user is None: - falcon.responders.path_not_found( - request, response, b'404 Not Found') + not_found(response) else: - response.status = falcon.HTTP_200 - resource = self._make_collection(request) - response.body = etag(resource) + okay(response, etag(self._make_collection(request))) def on_post(self, request, response): """POST to /addresses @@ -190,7 +183,7 @@ class UserAddresses(_AddressBase): Add a new address to the user record. """ if self._user is None: - falcon.responders.path_not_found(request, response) + not_found(response) return user_manager = getUtility(IUserManager) validator = Validator(email=unicode, @@ -199,19 +192,15 @@ class UserAddresses(_AddressBase): try: address = user_manager.create_address(**validator(request)) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, body=str(error)) except InvalidEmailAddressError: - falcon.responders.bad_request( - request, response, body=b'Invalid email address') + bad_request(response, body=b'Invalid email address') except ExistingAddressError: - falcon.responders.bad_request( - request, response, body=b'Address already exists') + bad_request(response, b'Address already exists') else: # Link the address to the current user and return it. address.user = self._user - location = path_to('addresses/{0}'.format(address.email)) - response.status = falcon.HTTP_201 - response.location = location + created(response, path_to('addresses/{0}'.format(address.email))) diff --git a/src/mailman/rest/configuration.py b/src/mailman/rest/configuration.py index 532f7bc4d..1e05ce8c0 100644 --- a/src/mailman/rest/configuration.py +++ b/src/mailman/rest/configuration.py @@ -25,8 +25,6 @@ __all__ = [ ] -import falcon - from lazr.config import as_boolean, as_timedelta from mailman.config import config from mailman.core.errors import ( @@ -35,7 +33,8 @@ from mailman.interfaces.action import Action from mailman.interfaces.archiver import ArchivePolicy from mailman.interfaces.autorespond import ResponseAction from mailman.interfaces.mailinglist import IAcceptableAliasSet, ReplyToMunging -from mailman.rest.helpers import GetterSetter, etag +from mailman.rest.helpers import ( + GetterSetter, bad_request, etag, no_content, okay) from mailman.rest.validator import PatchValidator, Validator, enum_validator @@ -172,16 +171,15 @@ class ListConfiguration: value = ATTRIBUTES[attribute].get(self._mlist, attribute) resource[attribute] = value elif self._attribute not in ATTRIBUTES: - falcon.responders.bad_request( - request, response, + bad_request( + response, body=b'Unknown attribute: {0}'.format(self._attribute)) return else: attribute = self._attribute value = ATTRIBUTES[attribute].get(self._mlist, attribute) resource[attribute] = value - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) def on_put(self, request, response): """Set a mailing list configuration.""" @@ -191,46 +189,41 @@ class ListConfiguration: try: validator.update(self._mlist, request) except ValueError as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, body=str(error)) return elif attribute not in ATTRIBUTES: - falcon.responders.bad_request( - request, response, - body=b'Unknown attribute: {0}'.format(attribute)) + bad_request(response, b'Unknown attribute: {0}'.format(attribute)) return elif ATTRIBUTES[attribute].decoder is None: - falcon.responders.bad_request( - request, response, - body=b'Read-only attribute: {0}'.format(attribute)) + bad_request( + response, b'Read-only attribute: {0}'.format(attribute)) return else: validator = Validator(**{attribute: VALIDATORS[attribute]}) try: validator.update(self._mlist, request) except ValueError as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, str(error)) return - response.status = falcon.HTTP_204 + no_content(response) def on_patch(self, request, response): """Patch the configuration (i.e. partial update).""" try: validator = PatchValidator(request, ATTRIBUTES) except UnknownPATCHRequestError as error: - falcon.responders.bad_request( - request, response, + bad_request( + response, body=b'Unknown attribute: {0}'.format(error.attribute)) return except ReadOnlyPATCHRequestError as error: - falcon.responders.bad_request( - request, response, + bad_request( + response, body=b'Read-only attribute: {0}'.format(error.attribute)) return try: validator.update(self._mlist, request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) else: - response.status = falcon.HTTP_204 + no_content(response) diff --git a/src/mailman/rest/domains.py b/src/mailman/rest/domains.py index 23b1c6b3c..5d36dcab9 100644 --- a/src/mailman/rest/domains.py +++ b/src/mailman/rest/domains.py @@ -26,12 +26,11 @@ __all__ = [ ] -import falcon - from mailman.interfaces.domain import ( BadDomainSpecificationError, IDomainManager) from mailman.rest.helpers import ( - BadRequest, CollectionMixin, NotFound, child, etag, path_to) + BadRequest, CollectionMixin, NotFound, bad_request, child, created, etag, + no_content, not_found, okay, path_to) from mailman.rest.lists import ListsForDomain from mailman.rest.validator import Validator from zope.component import getUtility @@ -67,10 +66,9 @@ class ADomain(_DomainBase): """Return a single domain end-point.""" domain = getUtility(IDomainManager).get(self._domain) if domain is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = self._resource_as_json(domain) + okay(response, self._resource_as_json(domain)) def on_delete(self, request, response): """Delete the domain.""" @@ -78,10 +76,9 @@ class ADomain(_DomainBase): getUtility(IDomainManager).remove(self._domain) except KeyError: # The domain does not exist. - falcon.responders.path_not_found( - request, response, '404 Not Found') + not_found(response) else: - response.status = falcon.HTTP_204 + no_content(response) @child() def lists(self, request, segments): @@ -110,18 +107,13 @@ class AllDomains(_DomainBase): 'contact_address')) domain = domain_manager.add(**validator(request)) except BadDomainSpecificationError: - falcon.responders.bad_request( - request, response, body=b'Domain exists') + bad_request(response, b'Domain exists') except ValueError as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, str(error)) else: - location = path_to('domains/{0}'.format(domain.mail_host)) - response.status = falcon.HTTP_201 - response.location = location + created(response, path_to('domains/{0}'.format(domain.mail_host))) def on_get(self, request, response): """/domains""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) diff --git a/src/mailman/rest/helpers.py b/src/mailman/rest/helpers.py index 74c66958d..acc5106be 100644 --- a/src/mailman/rest/helpers.py +++ b/src/mailman/rest/helpers.py @@ -25,8 +25,15 @@ __all__ = [ 'ChildError', 'GetterSetter', 'NotFound', + 'bad_request', 'child', + 'conflict', + 'created', 'etag', + 'forbidden', + 'no_content', + 'not_found', + 'okay', 'path_to', ] @@ -272,3 +279,42 @@ class BadRequest(ChildError): class NotFound(ChildError): def __init__(self): super(NotFound, self).__init__(falcon.HTTP_404) + + +def okay(response, body=None): + response.status = falcon.HTTP_200 + if body is not None: + response.body = body + + +def no_content(response): + response.status = falcon.HTTP_204 + + +def not_found(response, body=b'404 Not Found'): + response.status = falcon.HTTP_404 + if body is not None: + response.body = body + + +def bad_request(response, body='400 Bad Request'): + response.status = falcon.HTTP_400 + if body is not None: + response.body = body + + +def created(response, location): + response.status = falcon.HTTP_201 + response.location = location + + +def conflict(response, body=b'409 Conflict'): + response.status = falcon.HTTP_409 + if body is not None: + response.body = body + + +def forbidden(response, body=b'403 Forbidden'): + response.status = falcon.HTTP_403 + if body is not None: + response.body = body diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py index 0aaa6298f..580b6e898 100644 --- a/src/mailman/rest/lists.py +++ b/src/mailman/rest/lists.py @@ -30,8 +30,6 @@ __all__ = [ ] -import falcon - from lazr.config import as_boolean from operator import attrgetter from zope.component import getUtility @@ -47,7 +45,8 @@ from mailman.interfaces.styles import IStyleManager from mailman.interfaces.subscriptions import ISubscriptionService from mailman.rest.configuration import ListConfiguration from mailman.rest.helpers import ( - CollectionMixin, GetterSetter, NotFound, child, etag, paginate, path_to) + CollectionMixin, GetterSetter, NotFound, bad_request, child, created, + etag, no_content, not_found, okay, paginate, path_to) from mailman.rest.members import AMember, MemberCollection from mailman.rest.moderation import HeldMessages, SubscriptionRequests from mailman.rest.validator import Validator @@ -138,18 +137,17 @@ class AList(_ListBase): def on_get(self, request, response): """Return a single mailing list end-point.""" if self._mlist is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = self._resource_as_json(self._mlist) + okay(response, self._resource_as_json(self._mlist)) def on_delete(self, request, response): """Delete the named mailing list.""" if self._mlist is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: remove_list(self._mlist) - response.status = falcon.HTTP_204 + no_content(response) @child(member_matcher) def member(self, request, segments, role, email): @@ -211,25 +209,20 @@ class AllLists(_ListBase): _optional=('style_name',)) mlist = create_list(**validator(request)) except ListAlreadyExistsError: - falcon.responders.bad_request( - request, response, body=b'Mailing list exists') + bad_request(response, b'Mailing list exists') except BadDomainSpecificationError as error: - falcon.responders.bad_request( - request, response, body=b'Domain does not exist: {0}'.format( - error.domain)) + bad_request( + response, + b'Domain does not exist: {0}'.format(error.domain)) except ValueError as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, str(error)) else: - location = path_to('lists/{0}'.format(mlist.list_id)) - response.status = falcon.HTTP_201 - response.location = location + created(response, path_to('lists/{0}'.format(mlist.list_id))) def on_get(self, request, response): """/lists""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @@ -260,8 +253,7 @@ class ListsForDomain(_ListBase): def on_get(self, request, response): """/domains/<domain>/lists""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @paginate def _get_collection(self, request): @@ -298,8 +290,7 @@ class ListArchivers: archiver_set = IListArchiverSet(self._mlist) resource = {archiver.name: archiver.is_enabled for archiver in archiver_set.archivers} - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) def patch_put(self, request, response, is_optional): archiver_set = IListArchiverSet(self._mlist) @@ -311,9 +302,9 @@ class ListArchivers: try: Validator(**kws).update(self._mlist, request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) else: - response.status = falcon.HTTP_204 + no_content(response) def on_put(self, request, response): """Update all the archiver statuses.""" @@ -336,5 +327,4 @@ class Styles: default=config.styles.default) def on_get(self, request, response): - response.status = falcon.HTTP_200 - response.body = etag(self._resource) + okay(response, etag(self._resource)) diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py index afc4b302d..4d1c87b73 100644 --- a/src/mailman/rest/members.py +++ b/src/mailman/rest/members.py @@ -28,8 +28,6 @@ __all__ = [ ] -import falcon - from uuid import UUID from operator import attrgetter from zope.component import getUtility @@ -44,7 +42,8 @@ from mailman.interfaces.subscriptions import ISubscriptionService from mailman.interfaces.user import UnverifiedAddressError from mailman.interfaces.usermanager import IUserManager from mailman.rest.helpers import ( - CollectionMixin, NotFound, child, etag, paginate, path_to) + CollectionMixin, NotFound, bad_request, child, conflict, created, etag, + no_content, not_found, okay, paginate, path_to) from mailman.rest.preferences import Preferences, ReadOnlyPreferences from mailman.rest.validator import ( Validator, enum_validator, subscriber_validator) @@ -98,8 +97,7 @@ class MemberCollection(_MemberBase): def on_get(self, request, response): """roster/[members|owners|moderators]""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @@ -121,10 +119,9 @@ class AMember(_MemberBase): def on_get(self, request, response): """Return a single member end-point.""" if self._member is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = self._resource_as_json(self._member) + okay(response, self._resource_as_json(self._member)) @child() def preferences(self, request, segments): @@ -156,18 +153,18 @@ class AMember(_MemberBase): # owner. Handle the former case first. For now too, we will not send # an admin or user notification. if self._member is None: - falcon.responders.path_not_found(request, response) + not_found(response) return mlist = getUtility(IListManager).get_by_list_id(self._member.list_id) if self._member.role is MemberRole.member: try: delete_member(mlist, self._member.address.email, False, False) except NotAMemberError: - falcon.responders.path_not_found(request, response) + not_found(response) return else: self._member.unsubscribe() - response.status = falcon.HTTP_204 + no_content(response) def on_patch(self, request, response): """Patch the membership. @@ -175,7 +172,7 @@ class AMember(_MemberBase): This is how subscription changes are done. """ if self._member is None: - falcon.responders.path_not_found(request, response) + not_found(response) return try: values = Validator( @@ -183,24 +180,22 @@ class AMember(_MemberBase): delivery_mode=enum_validator(DeliveryMode), _optional=('address', 'delivery_mode'))(request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) return if 'address' in values: email = values['address'] address = getUtility(IUserManager).get_address(email) if address is None: - falcon.responders.bad_request( - request, response, body=b'Address not registered') + bad_request(response, b'Address not registered') return try: self._member.address = address except (MembershipError, UnverifiedAddressError) as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, str(error)) return if 'delivery_mode' in values: self._member.preferences.delivery_mode = values['delivery_mode'] - response.status = falcon.HTTP_204 + no_content(response) @@ -220,29 +215,24 @@ class AllMembers(_MemberBase): _optional=('delivery_mode', 'display_name', 'role')) member = service.join(**validator(request)) except AlreadySubscribedError: - response.status = falcon.HTTP_409 - response.body = b'Member already subscribed' + conflict(response, b'Member already subscribed') except NoSuchListError: - falcon.responders.bad_request( - request, response, body=b'No such list') + bad_request(response, b'No such list') except InvalidEmailAddressError: - falcon.responders.bad_request( - request, response, body=b'Invalid email address') + bad_request(response, b'Invalid email address') except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) else: # The member_id are UUIDs. We need to use the integer equivalent # in the URL. member_id = member.member_id.int location = path_to('members/{0}'.format(member_id)) - response.status = falcon.HTTP_201 - response.location = location + created(response, location) def on_get(self, request, response): """/members""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @@ -273,8 +263,7 @@ class FindMembers(_MemberBase): try: members = service.find_members(**validator(request)) except ValueError as error: - falcon.responders.bad_request(response, body=str(error)) + bad_request(response, str(error)) else: resource = _FoundMembers(members)._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) diff --git a/src/mailman/rest/moderation.py b/src/mailman/rest/moderation.py index 97371168d..0bdc50688 100644 --- a/src/mailman/rest/moderation.py +++ b/src/mailman/rest/moderation.py @@ -28,14 +28,13 @@ __all__ = [ ] -import falcon - from mailman.app.moderator import ( handle_message, handle_subscription, handle_unsubscription) from mailman.interfaces.action import Action from mailman.interfaces.messages import IMessageStore from mailman.interfaces.requests import IListRequests, RequestType -from mailman.rest.helpers import CollectionMixin, child, etag +from mailman.rest.helpers import ( + CollectionMixin, bad_request, child, etag, no_content, not_found, okay) from mailman.rest.validator import Validator, enum_validator from zope.component import getUtility @@ -112,35 +111,33 @@ class HeldMessage(_HeldMessageBase): try: request_id = int(self._request_id) except ValueError: - falcon.responders.bad_request(request, response) + bad_request(response) return resource = self._make_resource(request_id) if resource is None: - falcon.responders.path_not_found( - request, response, body=b'404 Not Found') + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action)) arguments = validator(request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) return requests = IListRequests(self._mlist) try: request_id = int(self._request_id) except ValueError: - falcon.responders.bad_request(request, response) + bad_request(response) return results = requests.get_request(request_id, RequestType.held_message) if results is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: handle_message(self._mlist, request_id, **arguments) - response.status = falcon.HTTP_204 + no_content(response) @@ -163,8 +160,7 @@ class HeldMessages(_HeldMessageBase, CollectionMixin): def on_get(self, request, response): """/lists/listname/held""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @child(r'^(?P<id>[^/]+)') def message(self, request, segments, **kw): @@ -183,48 +179,47 @@ class MembershipChangeRequest(_ModerationBase): try: request_id = int(self._request_id) except ValueError: - falcon.responders.bad_request(request, response) + bad_request(response) return resource = self._make_resource(request_id, MEMBERSHIP_CHANGE_REQUESTS) if resource is None: - falcon.responders.path_not_found(request, response) + not_found(response) else: # Remove unnecessary keys. del resource['key'] - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action)) arguments = validator(request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) return requests = IListRequests(self._mlist) try: request_id = int(self._request_id) except ValueError: - falcon.responders.bad_request(request, response) + bad_request(response) return results = requests.get_request(request_id) if results is None: - falcon.responders.path_not_found(request, response) + not_found(response) return key, data = results try: request_type = RequestType[data['_request_type']] except ValueError: - falcon.responders.bad_request(request, response) + bad_request(response) return if request_type is RequestType.subscription: handle_subscription(self._mlist, request_id, **arguments) elif request_type is RequestType.unsubscription: handle_unsubscription(self._mlist, request_id, **arguments) else: - falcon.responders.bad_request(request, response) + bad_request(response) return - response.status = falcon.HTTP_204 + no_content(response) class SubscriptionRequests(_ModerationBase, CollectionMixin): @@ -253,8 +248,7 @@ class SubscriptionRequests(_ModerationBase, CollectionMixin): def on_get(self, request, response): """/lists/listname/requests""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @child(r'^(?P<id>[^/]+)') def subscription(self, request, segments, **kw): diff --git a/src/mailman/rest/preferences.py b/src/mailman/rest/preferences.py index fdd1f65fb..b85388ec9 100644 --- a/src/mailman/rest/preferences.py +++ b/src/mailman/rest/preferences.py @@ -26,11 +26,10 @@ __all__ = [ ] -import falcon - from lazr.config import as_boolean from mailman.interfaces.member import DeliveryMode, DeliveryStatus -from mailman.rest.helpers import GetterSetter, etag, path_to +from mailman.rest.helpers import ( + GetterSetter, bad_request, etag, no_content, not_found, okay, path_to) from mailman.rest.validator import ( Validator, enum_validator, language_validator) @@ -70,8 +69,7 @@ class ReadOnlyPreferences: # Add the self link. resource['self_link'] = path_to( '{0}/preferences'.format(self._base_url)) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) @@ -80,7 +78,8 @@ class Preferences(ReadOnlyPreferences): def patch_put(self, request, response, is_optional): if self._parent is None: - response.status = falcon.HTTP_404 + not_found(response) + return kws = dict( acknowledge_posts=GetterSetter(as_boolean), hide_address = GetterSetter(as_boolean), @@ -96,10 +95,9 @@ class Preferences(ReadOnlyPreferences): try: Validator(**kws).update(self._parent, request) except ValueError as error: - falcon.responders.bad_request( - request, response, body=str(error)) + bad_request(response, str(error)) else: - response.status = falcon.HTTP_204 + no_content(response) def on_patch(self, request, response): """Patch the preferences.""" @@ -114,4 +112,4 @@ class Preferences(ReadOnlyPreferences): for attr in PREFERENCES: if hasattr(self._parent, attr): setattr(self._parent, attr, None) - response.status = falcon.HTTP_204 + no_content(response) diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py index 5db59ad7d..93a8f0086 100644 --- a/src/mailman/rest/root.py +++ b/src/mailman/rest/root.py @@ -36,7 +36,8 @@ from mailman.core.system import system from mailman.interfaces.listmanager import IListManager from mailman.rest.addresses import AllAddresses, AnAddress from mailman.rest.domains import ADomain, AllDomains -from mailman.rest.helpers import BadRequest, NotFound, child, etag, path_to +from mailman.rest.helpers import ( + BadRequest, NotFound, child, etag, okay, path_to) from mailman.rest.lists import AList, AllLists, Styles from mailman.rest.members import AMember, AllMembers, FindMembers from mailman.rest.preferences import ReadOnlyPreferences @@ -87,8 +88,7 @@ class System: python_version=system.python_version, self_link=path_to('system'), ) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) class TopLevel: diff --git a/src/mailman/rest/templates.py b/src/mailman/rest/templates.py index 85c698f07..44dcdefc5 100644 --- a/src/mailman/rest/templates.py +++ b/src/mailman/rest/templates.py @@ -25,8 +25,7 @@ __all__ = [ ] -import falcon - +from mailman.rest.helpers import not_found from mailman.utilities.i18n import TemplateNotFoundError, find @@ -51,7 +50,7 @@ class TemplateFinder: # XXX We currently only support .txt and .html files. extension = EXTENSIONS.get(self.content_type) if extension is None: - falcon.responders.path_not_found(request, response) + not_found(response) return template = self.template + extension fp = None @@ -59,7 +58,7 @@ class TemplateFinder: try: path, fp = find(template, self.mlist, self.language) except TemplateNotFoundError: - falcon.responders.path_not_found(request, response) + not_found(response) return else: return fp.read() diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py index cccd5ab98..645b83a36 100644 --- a/src/mailman/rest/users.py +++ b/src/mailman/rest/users.py @@ -26,8 +26,6 @@ __all__ = [ ] -import falcon - from passlib.utils import generate_password as generate from uuid import UUID from zope.component import getUtility @@ -39,8 +37,8 @@ from mailman.interfaces.address import ExistingAddressError from mailman.interfaces.usermanager import IUserManager from mailman.rest.addresses import UserAddresses from mailman.rest.helpers import ( - BadRequest, CollectionMixin, GetterSetter, NotFound, child, etag, - paginate, path_to) + BadRequest, CollectionMixin, GetterSetter, NotFound, bad_request, child, + created, etag, forbidden, no_content, not_found, okay, paginate, path_to) from mailman.rest.preferences import Preferences from mailman.rest.validator import PatchValidator, Validator @@ -101,8 +99,7 @@ class AllUsers(_UserBase): def on_get(self, request, response): """/users""" resource = self._make_collection(request) - response.status = falcon.HTTP_200 - response.body = etag(resource) + okay(response, etag(resource)) def on_post(self, request, response): """Create a new user.""" @@ -113,7 +110,7 @@ class AllUsers(_UserBase): _optional=('display_name', 'password')) arguments = validator(request) except ValueError as error: - falcon.responders.bad_request(response, body=str(error)) + bad_request(response, str(error)) return # We can't pass the 'password' argument to the user creation method, # so strip that out (if it exists), then create the user, adding the @@ -122,8 +119,8 @@ class AllUsers(_UserBase): try: user = getUtility(IUserManager).create_user(**arguments) except ExistingAddressError as error: - falcon.responders.bad_request( - request, response, + bad_request( + response, body=b'Address already exists: {0}'.format(error.address)) return if password is None: @@ -131,8 +128,7 @@ class AllUsers(_UserBase): password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) location = path_to('users/{0}'.format(user.user_id.int)) - response.status = falcon.HTTP_201 - response.location = location + created(response, location) @@ -165,11 +161,9 @@ class AUser(_UserBase): def on_get(self, request, response): """Return a single user end-point.""" if self._user is None: - falcon.responders.path_not_found( - request, response, body=b'404 Not Found') + not_found(response) else: - response.status = falcon.HTTP_200 - response.body = self._resource_as_json(self._user) + okay(response, self._resource_as_json(self._user)) @child() def addresses(self, request, segments): @@ -181,7 +175,7 @@ class AUser(_UserBase): def on_delete(self, request, response): """Delete the named user, all her memberships, and addresses.""" if self._user is None: - falcon.responders.path_not_found(request, response) + not_found(response) return for member in self._user.memberships.members: member.unsubscribe() @@ -189,7 +183,7 @@ class AUser(_UserBase): for address in self._user.addresses: user_manager.delete_address(address) user_manager.delete_user(self._user) - response.status = falcon.HTTP_204 + no_content(response) @child() def preferences(self, request, segments): @@ -206,44 +200,38 @@ class AUser(_UserBase): def on_patch(self, request, response): """Patch the user's configuration (i.e. partial update).""" if self._user is None: - falcon.responders.path_not_found(request, response) + not_found(response) return try: validator = PatchValidator(request, ATTRIBUTES) except UnknownPATCHRequestError as error: - falcon.responders.bad_request( - request, response, - body=b'Unknown attribute: {0}'.format(error.attribute)) + bad_request( + response, b'Unknown attribute: {0}'.format(error.attribute)) except ReadOnlyPATCHRequestError as error: - falcon.responders.bad_request( - request, response, - body=b'Read-only attribute: {0}'.format(error.attribute)) + bad_request( + response, b'Read-only attribute: {0}'.format(error.attribute)) else: validator.update(self._user, request) - response.status = falcon.HTTP_204 + no_content(response) def on_put(self, request, response): """Put the user's configuration (i.e. full update).""" if self._user is None: - falcon.responders.path_not_found(request, response) + not_found(response) return validator = Validator(**ATTRIBUTES) try: validator.update(self._user, request) except UnknownPATCHRequestError as error: - falcon.responders.bad_request( - request, response, - body=b'Unknown attribute: {0}'.format(error.attribute)) + bad_request( + response, b'Unknown attribute: {0}'.format(error.attribute)) except ReadOnlyPATCHRequestError as error: - falcon.responders.bad_request( - request, response, - body=b'Read-only attribute: {0}'.format(error.attribute)) + bad_request( + response, b'Read-only attribute: {0}'.format(error.attribute)) except ValueError as error: - falcon.responders.bad_request( - request, response, - body=str(error)) + bad_request(response, str(error)) else: - response.status = falcon.HTTP_204 + no_content(response) @child() def login(self, request, segments): @@ -269,14 +257,13 @@ class Login: try: values = validator(request) except ValueError as error: - falcon.responders.bad_request(request, response, body=str(error)) + bad_request(response, str(error)) return is_valid, new_hash = config.password_context.verify( values['cleartext_password'], self._user.password) if is_valid: if new_hash is not None: self._user.password = new_hash - response.status = falcon.HTTP_204 + no_content(response) else: - response.status = falcon.HTTP_403 - response.body = b'403 Forbidden' + forbidden(response) diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index 341a4cbb4..98239ec51 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -27,18 +27,16 @@ __all__ = [ import re -import falcon import logging from falcon import API from falcon.api_helpers import create_http_method_map - -from wsgiref.simple_server import WSGIRequestHandler -from wsgiref.simple_server import make_server as wsgi_server - +from falcon.responders import path_not_found from mailman.config import config from mailman.database.transaction import transactional from mailman.rest.root import Root +from wsgiref.simple_server import WSGIRequestHandler +from wsgiref.simple_server import make_server as wsgi_server log = logging.getLogger('mailman.http') @@ -148,7 +146,7 @@ class RootedAPI(API): else: # None of the attributes matched this path component, so the # response is a 404. - return falcon.responders.path_not_found, {}, None + return path_not_found, {}, None |
