summaryrefslogtreecommitdiff
path: root/src/mailman/rest/lists.py
diff options
context:
space:
mode:
authorBarry Warsaw2014-11-15 12:01:30 -0500
committerBarry Warsaw2014-11-15 12:01:30 -0500
commit26fe2c0d37d4da51dbda077cdf46a4cd6cec22a5 (patch)
tree4c5f78bcb5236921291b30d15003666d58c47194 /src/mailman/rest/lists.py
parent50127508451e1099e9e48266c1fb05b3d1ee2a4b (diff)
parent368100001d11a7585dd424613fbc905269596ebd (diff)
downloadmailman-26fe2c0d37d4da51dbda077cdf46a4cd6cec22a5.tar.gz
mailman-26fe2c0d37d4da51dbda077cdf46a4cd6cec22a5.tar.zst
mailman-26fe2c0d37d4da51dbda077cdf46a4cd6cec22a5.zip
Diffstat (limited to 'src/mailman/rest/lists.py')
-rw-r--r--src/mailman/rest/lists.py127
1 files changed, 66 insertions, 61 deletions
diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py
index 552824927..580b6e898 100644
--- a/src/mailman/rest/lists.py
+++ b/src/mailman/rest/lists.py
@@ -26,32 +26,33 @@ __all__ = [
'ListArchivers',
'ListConfiguration',
'ListsForDomain',
+ 'Styles',
]
from lazr.config import as_boolean
from operator import attrgetter
-from restish import http, resource
from zope.component import getUtility
from mailman.app.lifecycle import create_list, remove_list
+from mailman.config import config
from mailman.interfaces.domain import BadDomainSpecificationError
from mailman.interfaces.listmanager import (
IListManager, ListAlreadyExistsError)
from mailman.interfaces.mailinglist import IListArchiverSet
from mailman.interfaces.member import MemberRole
+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, PATCH, etag, no_content, paginate, path_to,
- restish_matcher)
+ 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
-@restish_matcher
def member_matcher(request, segments):
"""A matcher of member URLs inside mailing lists.
@@ -64,13 +65,9 @@ def member_matcher(request, segments):
except KeyError:
# Not a valid role.
return None
- # No more segments.
- # XXX 2010-02-25 barry Matchers are undocumented in restish; they return a
- # 3-tuple of (match_args, match_kws, segments).
return (), dict(role=role, email=segments[1]), ()
-@restish_matcher
def roster_matcher(request, segments):
"""A matcher of all members URLs inside mailing lists.
@@ -85,7 +82,6 @@ def roster_matcher(request, segments):
return None
-@restish_matcher
def config_matcher(request, segments):
"""A matcher for a mailing list's configuration resource.
@@ -103,7 +99,7 @@ def config_matcher(request, segments):
-class _ListBase(resource.Resource, CollectionMixin):
+class _ListBase(CollectionMixin):
"""Shared base class for mailing list representations."""
def _resource_as_dict(self, mlist):
@@ -138,66 +134,66 @@ class AList(_ListBase):
else:
self._mlist = manager.get_by_list_id(list_identifier)
- @resource.GET()
- def mailing_list(self, request):
+ def on_get(self, request, response):
"""Return a single mailing list end-point."""
if self._mlist is None:
- return http.not_found()
- return http.ok([], self._resource_as_json(self._mlist))
+ not_found(response)
+ else:
+ okay(response, self._resource_as_json(self._mlist))
- @resource.DELETE()
- def delete_list(self, request):
+ def on_delete(self, request, response):
"""Delete the named mailing list."""
if self._mlist is None:
- return http.not_found()
- remove_list(self._mlist)
- return no_content()
+ not_found(response)
+ else:
+ remove_list(self._mlist)
+ no_content(response)
- @resource.child(member_matcher)
+ @child(member_matcher)
def member(self, request, segments, role, email):
"""Return a single member representation."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
members = getUtility(ISubscriptionService).find_members(
email, self._mlist.list_id, role)
if len(members) == 0:
- return http.not_found()
+ return NotFound(), []
assert len(members) == 1, 'Too many matches'
return AMember(members[0].member_id)
- @resource.child(roster_matcher)
+ @child(roster_matcher)
def roster(self, request, segments, role):
"""Return the collection of all a mailing list's members."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
return MembersOfList(self._mlist, role)
- @resource.child(config_matcher)
+ @child(config_matcher)
def config(self, request, segments, attribute=None):
"""Return a mailing list configuration object."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
return ListConfiguration(self._mlist, attribute)
- @resource.child()
+ @child()
def held(self, request, segments):
"""Return a list of held messages for the mailing list."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
return HeldMessages(self._mlist)
- @resource.child()
+ @child()
def requests(self, request, segments):
"""Return a list of subscription/unsubscription requests."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
return SubscriptionRequests(self._mlist)
- @resource.child()
+ @child()
def archivers(self, request, segments):
"""Return a representation of mailing list archivers."""
if self._mlist is None:
- return http.not_found()
+ return NotFound(), []
return ListArchivers(self._mlist)
@@ -205,8 +201,7 @@ class AList(_ListBase):
class AllLists(_ListBase):
"""The mailing lists."""
- @resource.POST()
- def create(self, request):
+ def on_post(self, request, response):
"""Create a new mailing list."""
try:
validator = Validator(fqdn_listname=unicode,
@@ -214,22 +209,20 @@ class AllLists(_ListBase):
_optional=('style_name',))
mlist = create_list(**validator(request))
except ListAlreadyExistsError:
- return http.bad_request([], b'Mailing list exists')
+ bad_request(response, b'Mailing list exists')
except BadDomainSpecificationError as error:
- return http.bad_request([], 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:
- return http.bad_request([], str(error))
- # wsgiref wants headers to be bytes, not unicodes.
- location = path_to('lists/{0}'.format(mlist.list_id))
- # Include no extra headers or body.
- return http.created(location, [], None)
+ bad_request(response, str(error))
+ else:
+ created(response, path_to('lists/{0}'.format(mlist.list_id)))
- @resource.GET()
- def collection(self, request):
+ def on_get(self, request, response):
"""/lists"""
resource = self._make_collection(request)
- return http.ok([], etag(resource))
+ okay(response, etag(resource))
@@ -257,11 +250,10 @@ class ListsForDomain(_ListBase):
def __init__(self, domain):
self._domain = domain
- @resource.GET()
- def collection(self, request):
+ def on_get(self, request, response):
"""/domains/<domain>/lists"""
resource = self._make_collection(request)
- return http.ok([], etag(resource))
+ okay(response, etag(resource))
@paginate
def _get_collection(self, request):
@@ -287,21 +279,20 @@ class ArchiverGetterSetter(GetterSetter):
archiver.is_enabled = as_boolean(value)
-class ListArchivers(resource.Resource):
+class ListArchivers:
"""The archivers for a list, with their enabled flags."""
def __init__(self, mlist):
self._mlist = mlist
- @resource.GET()
- def statuses(self, request):
+ def on_get(self, request, response):
"""Get all the archiver statuses."""
archiver_set = IListArchiverSet(self._mlist)
resource = {archiver.name: archiver.is_enabled
for archiver in archiver_set.archivers}
- return http.ok([], etag(resource))
+ okay(response, etag(resource))
- def patch_put(self, request, is_optional):
+ def patch_put(self, request, response, is_optional):
archiver_set = IListArchiverSet(self._mlist)
kws = {archiver.name: ArchiverGetterSetter(self._mlist)
for archiver in archiver_set.archivers}
@@ -311,15 +302,29 @@ class ListArchivers(resource.Resource):
try:
Validator(**kws).update(self._mlist, request)
except ValueError as error:
- return http.bad_request([], str(error))
- return no_content()
+ bad_request(response, str(error))
+ else:
+ no_content(response)
- @resource.PUT()
- def put_statuses(self, request):
+ def on_put(self, request, response):
"""Update all the archiver statuses."""
- return self.patch_put(request, is_optional=False)
+ self.patch_put(request, response, is_optional=False)
- @PATCH()
- def patch_statuses(self, request):
+ def on_patch(self, request, response):
"""Patch some archiver statueses."""
- return self.patch_put(request, is_optional=True)
+ self.patch_put(request, response, is_optional=True)
+
+
+
+class Styles:
+ """Simple resource representing all list styles."""
+
+ def __init__(self):
+ manager = getUtility(IStyleManager)
+ style_names = sorted(style.name for style in manager.styles)
+ self._resource = dict(
+ style_names=style_names,
+ default=config.styles.default)
+
+ def on_get(self, request, response):
+ okay(response, etag(self._resource))