diff options
| author | Barry Warsaw | 2010-02-25 20:38:25 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2010-02-25 20:38:25 -0500 |
| commit | b2ae2b7795719f17cb2b6c7ed14e5b4c7c8eae47 (patch) | |
| tree | 40233249ecb3c71f834cb5db7e33b9e56c3b1b4f /src/mailman/rest/members.py | |
| parent | ea7bb1a31c51a59949310c9837020908476e2c0d (diff) | |
| download | mailman-b2ae2b7795719f17cb2b6c7ed14e5b4c7c8eae47.tar.gz mailman-b2ae2b7795719f17cb2b6c7ed14e5b4c7c8eae47.tar.zst mailman-b2ae2b7795719f17cb2b6c7ed14e5b4c7c8eae47.zip | |
Refactor both the mailing lists and membership REST wrappers.
Diffstat (limited to 'src/mailman/rest/members.py')
| -rw-r--r-- | src/mailman/rest/members.py | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py new file mode 100644 index 000000000..b18097935 --- /dev/null +++ b/src/mailman/rest/members.py @@ -0,0 +1,138 @@ +# Copyright (C) 2010 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""REST for members.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + 'AMember', + 'AllMembers', + ] + + +from restish import http, resource +from zope.component import getUtility + +from mailman.app.membership import delete_member +from mailman.interfaces.address import InvalidEmailAddressError +from mailman.interfaces.listmanager import NoSuchListError +from mailman.interfaces.member import AlreadySubscribedError, MemberRole +from mailman.interfaces.membership import ISubscriptionService +from mailman.rest.helpers import etag, path_to + + + +class _MemberBase(resource.Resource): + """Shared base class for member representations.""" + + def _member_data(self, member): + """Return the member data for a single member.""" + enum, dot, role = str(member.role).partition('.') + return dict( + self_link=path_to('lists/{0}/{1}/{2}'.format( + member.mailing_list, role, member.address.address)), + ) + + def _format_member(self, member): + """Format the data for a single member.""" + return etag(self._member_data(member)) + + +class AMember(_MemberBase): + """A member.""" + + def __init__(self, mailing_list, role, address): + self._mlist = mailing_list + self._role = role + self._address = address + # XXX 2010-02-24 barry There should be a more direct way to get a + # member out of a mailing list. + if self._role is MemberRole.member: + roster = self._mlist.members + elif self._role is MemberRole.owner: + roster = self._mlist.owners + elif self._role is MemberRole.moderator: + roster = self._mlist.moderators + else: + raise AssertionError( + 'Undefined MemberRole: {0}'.format(self._role)) + self._member = roster.get_member(self._address) + + @resource.GET() + def member(self, request): + """Return a single member end-point.""" + return http.ok([], self._format_member(self._member)) + + @resource.DELETE() + def delete(self, request): + """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._role is MemberRole.member: + delete_member(self._mlist, self._address, False, False) + else: + self._member.unsubscribe() + return http.ok([], '') + + +class AllMembers(_MemberBase): + """The members.""" + + @resource.POST() + def create(self, request): + """Create a new member.""" + # XXX 2010-02-23 barry Sanity check the POST arguments by + # introspection of the target method, or via descriptors. + service = getUtility(ISubscriptionService) + try: + # webob gives this to us as a string, but we need unicodes. + kws = dict((key, unicode(value)) + for key, value in request.POST.items()) + member = service.join(**kws) + except AlreadySubscribedError: + return http.bad_request([], b'Member already subscribed') + except NoSuchListError: + return http.bad_request([], b'No such list') + except InvalidEmailAddressError: + return http.bad_request([], b'Invalid email address') + except ValueError as error: + return http.bad_request([], str(error)) + # wsgiref wants headers to be bytes, not unicodes. + location = path_to('lists/{0}/member/{1}'.format( + member.mailing_list, member.address.address)) + # Include no extra headers or body. + return http.created(location, [], None) + + @resource.GET() + def container(self, request): + """Return the /members end-point.""" + members = list(getUtility(ISubscriptionService)) + if len(members) == 0: + resource = dict(start=None, total_size=0) + return http.ok([], etag(resource)) + entries = [self._member_data(member) for member in members] + # Tag the domain entries, but use the dictionaries. + [etag(data) for data in entries] + resource = dict( + start=0, + total_size=len(members), + entries=entries, + ) + return http.ok([], etag(resource)) |
