summaryrefslogtreecommitdiff
path: root/src/mailman/rest/members.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/rest/members.py')
-rw-r--r--src/mailman/rest/members.py104
1 files changed, 52 insertions, 52 deletions
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index 51cbbd888..4d1c87b73 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -30,7 +30,6 @@ __all__ = [
from uuid import UUID
from operator import attrgetter
-from restish import http, resource
from zope.component import getUtility
from mailman.app.membership import delete_member
@@ -43,14 +42,15 @@ from mailman.interfaces.subscriptions import ISubscriptionService
from mailman.interfaces.user import UnverifiedAddressError
from mailman.interfaces.usermanager import IUserManager
from mailman.rest.helpers import (
- CollectionMixin, PATCH, etag, no_content, 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)
-class _MemberBase(resource.Resource, CollectionMixin):
+class _MemberBase(CollectionMixin):
"""Shared base class for member representations."""
def _resource_as_dict(self, member):
@@ -94,11 +94,10 @@ class MemberCollection(_MemberBase):
"""See `CollectionMixin`."""
raise NotImplementedError
- @resource.GET()
- def container(self, request):
+ def on_get(self, request, response):
"""roster/[members|owners|moderators]"""
resource = self._make_collection(request)
- return http.ok([], etag(resource))
+ okay(response, etag(resource))
@@ -117,90 +116,93 @@ class AMember(_MemberBase):
service = getUtility(ISubscriptionService)
self._member = service.get_member(member_id)
- @resource.GET()
- def member(self, request):
+ def on_get(self, request, response):
"""Return a single member end-point."""
if self._member is None:
- return http.not_found()
- return http.ok([], self._resource_as_json(self._member))
+ not_found(response)
+ else:
+ okay(response, self._resource_as_json(self._member))
- @resource.child()
+ @child()
def preferences(self, request, segments):
"""/members/<id>/preferences"""
if len(segments) != 0:
- return http.bad_request()
+ return NotFound(), []
if self._member is None:
- return http.not_found()
+ return NotFound(), []
child = Preferences(
self._member.preferences,
'members/{0}'.format(self._member.member_id.int))
return child, []
- @resource.child()
+ @child()
def all(self, request, segments):
"""/members/<id>/all/preferences"""
if len(segments) == 0:
- return http.not_found()
+ return NotFound(), []
if self._member is None:
- return http.not_found()
+ return NotFound(), []
child = ReadOnlyPreferences(
self._member,
'members/{0}/all'.format(self._member.member_id.int))
return child, []
- @resource.DELETE()
- def delete(self, request):
+ def on_delete(self, request, response):
"""Delete the member (i.e. unsubscribe)."""
# Leaving a list is a bit different than deleting a moderator or
# owner. Handle the former case first. For now too, we will not send
# an admin or user notification.
if self._member is None:
- return http.not_found()
+ 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:
- return http.not_found()
+ not_found(response)
+ return
else:
self._member.unsubscribe()
- return no_content()
+ no_content(response)
- @PATCH()
- def patch_membership(self, request):
+ def on_patch(self, request, response):
"""Patch the membership.
This is how subscription changes are done.
"""
if self._member is None:
- return http.not_found()
+ not_found(response)
+ return
try:
values = Validator(
address=unicode,
delivery_mode=enum_validator(DeliveryMode),
_optional=('address', 'delivery_mode'))(request)
except ValueError as error:
- return http.bad_request([], 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:
- return http.bad_request([], b'Address not registered')
+ bad_request(response, b'Address not registered')
+ return
try:
self._member.address = address
except (MembershipError, UnverifiedAddressError) as error:
- return http.bad_request([], str(error))
+ bad_request(response, str(error))
+ return
if 'delivery_mode' in values:
self._member.preferences.delivery_mode = values['delivery_mode']
- return no_content()
+ no_content(response)
class AllMembers(_MemberBase):
"""The members."""
- @resource.POST()
- def create(self, request):
+ def on_post(self, request, response):
"""Create a new member."""
service = getUtility(ISubscriptionService)
try:
@@ -213,25 +215,24 @@ class AllMembers(_MemberBase):
_optional=('delivery_mode', 'display_name', 'role'))
member = service.join(**validator(request))
except AlreadySubscribedError:
- return http.conflict([], b'Member already subscribed')
+ conflict(response, b'Member already subscribed')
except NoSuchListError:
- return http.bad_request([], b'No such list')
+ bad_request(response, b'No such list')
except InvalidEmailAddressError:
- return http.bad_request([], b'Invalid email address')
+ bad_request(response, b'Invalid email address')
except ValueError as error:
- return http.bad_request([], str(error))
- # 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))
- # Include no extra headers or body.
- return http.created(location, [], None)
+ 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))
+ created(response, location)
- @resource.GET()
- def container(self, request):
+ def on_get(self, request, response):
"""/members"""
resource = self._make_collection(request)
- return http.ok([], etag(resource))
+ okay(response, etag(resource))
@@ -251,8 +252,7 @@ class _FoundMembers(MemberCollection):
class FindMembers(_MemberBase):
"""/members/find"""
- @resource.POST()
- def find(self, request):
+ def on_post(self, request, response):
"""Find a member"""
service = getUtility(ISubscriptionService)
validator = Validator(
@@ -260,10 +260,10 @@ class FindMembers(_MemberBase):
subscriber=unicode,
role=enum_validator(MemberRole),
_optional=('list_id', 'subscriber', 'role'))
- members = service.find_members(**validator(request))
- # We can't just return the _FoundMembers instance, because
- # CollectionMixins have only a GET method, which is incompatible with
- # this POSTed resource. IOW, without doing this here, restish would
- # throw a 405 Method Not Allowed.
- resource = _FoundMembers(members)._make_collection(request)
- return http.ok([], etag(resource))
+ try:
+ members = service.find_members(**validator(request))
+ except ValueError as error:
+ bad_request(response, str(error))
+ else:
+ resource = _FoundMembers(members)._make_collection(request)
+ okay(response, etag(resource))