summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2014-08-13 00:18:23 -0400
committerBarry Warsaw2014-08-13 00:18:23 -0400
commit72dd28e26b1fa369de93652bd51869cebd79c0a3 (patch)
tree5a01056497024f280141e78f8e1a81b22c298fad
parentbc4e33da9a97df35d147e58535358b2468cd1cc8 (diff)
downloadmailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.tar.gz
mailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.tar.zst
mailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.zip
-rw-r--r--src/mailman/rest/addresses.py2
-rw-r--r--src/mailman/rest/docs/preferences.rst20
-rw-r--r--src/mailman/rest/members.py8
-rw-r--r--src/mailman/rest/preferences.py30
-rw-r--r--src/mailman/rest/tests/test_preferences.py67
-rw-r--r--src/mailman/rest/users.py2
6 files changed, 87 insertions, 42 deletions
diff --git a/src/mailman/rest/addresses.py b/src/mailman/rest/addresses.py
index d42a66aa7..f9a08b157 100644
--- a/src/mailman/rest/addresses.py
+++ b/src/mailman/rest/addresses.py
@@ -129,7 +129,7 @@ class AnAddress(_AddressBase):
return NotFound(), []
return AddressMemberships(self._address)
- @resource.child()
+ @child()
def preferences(self, request, segments):
"""/addresses/<email>/preferences"""
if len(segments) != 0:
diff --git a/src/mailman/rest/docs/preferences.rst b/src/mailman/rest/docs/preferences.rst
index 8694364a4..b8a0af500 100644
--- a/src/mailman/rest/docs/preferences.rst
+++ b/src/mailman/rest/docs/preferences.rst
@@ -199,21 +199,12 @@ Preferences accessed through this interface are always read only.
receive_own_postings: False
self_link: http://localhost:9001/3.0/members/1/all/preferences
-These preferences cannot be changed.
-
- >>> dump_json('http://localhost:9001/3.0/members/1/all/preferences', {
- ... 'delivery_status': 'enabled',
- ... }, method='PATCH')
- Traceback (most recent call last):
- ...
- HTTPError: HTTP Error 405: 405 Method Not Allowed
-
System preferences
==================
The Mailman system itself has a default set of preference. All preference
-lookups fall back to these values, which are read-only.
+look ups fall back to these values, which are read-only.
>>> dump_json('http://localhost:9001/3.0/system/preferences')
acknowledge_posts: False
@@ -225,12 +216,3 @@ lookups fall back to these values, which are read-only.
receive_list_copy: True
receive_own_postings: True
self_link: http://localhost:9001/3.0/system/preferences
-
-These preferences cannot be changed.
-
- >>> dump_json('http://localhost:9001/3.0/system/preferences', {
- ... 'delivery_status': 'enabled',
- ... }, method='PATCH')
- Traceback (most recent call last):
- ...
- HTTPError: HTTP Error 405: 405 Method Not Allowed
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index ae44ee2d5..b28a0d3e4 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -45,14 +45,14 @@ 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, PATCH, child, etag, no_content, 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):
@@ -126,7 +126,7 @@ class AMember(_MemberBase):
return http.not_found()
return http.ok([], self._resource_as_json(self._member))
- @resource.child()
+ @child()
def preferences(self, request, segments):
"""/members/<id>/preferences"""
if len(segments) != 0:
@@ -138,7 +138,7 @@ class AMember(_MemberBase):
'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:
diff --git a/src/mailman/rest/preferences.py b/src/mailman/rest/preferences.py
index d501ef865..fdd1f65fb 100644
--- a/src/mailman/rest/preferences.py
+++ b/src/mailman/rest/preferences.py
@@ -29,11 +29,8 @@ __all__ = [
import falcon
from lazr.config import as_boolean
-from restish import http, resource
-
from mailman.interfaces.member import DeliveryMode, DeliveryStatus
-from mailman.rest.helpers import (
- GetterSetter, PATCH, etag, no_content, path_to)
+from mailman.rest.helpers import GetterSetter, etag, path_to
from mailman.rest.validator import (
Validator, enum_validator, language_validator)
@@ -81,9 +78,9 @@ class ReadOnlyPreferences:
class Preferences(ReadOnlyPreferences):
"""Preferences which can be changed."""
- def patch_put(self, request, is_optional):
+ def patch_put(self, request, response, is_optional):
if self._parent is None:
- return http.not_found()
+ response.status = falcon.HTTP_404
kws = dict(
acknowledge_posts=GetterSetter(as_boolean),
hide_address = GetterSetter(as_boolean),
@@ -99,23 +96,22 @@ class Preferences(ReadOnlyPreferences):
try:
Validator(**kws).update(self._parent, request)
except ValueError as error:
- return http.bad_request([], str(error))
- return no_content()
+ falcon.responders.bad_request(
+ request, response, body=str(error))
+ else:
+ response.status = falcon.HTTP_204
- @PATCH()
- def patch_preferences(self, request):
+ def on_patch(self, request, response):
"""Patch the preferences."""
- return self.patch_put(request, is_optional=True)
+ self.patch_put(request, response, is_optional=True)
- @resource.PUT()
- def put_preferences(self, request):
+ def on_put(self, request, response):
"""Change all preferences."""
- return self.patch_put(request, is_optional=False)
+ self.patch_put(request, response, is_optional=False)
- @resource.DELETE()
- def delete_preferences(self, request):
+ def on_delete(self, request, response):
"""Delete all preferences."""
for attr in PREFERENCES:
if hasattr(self._parent, attr):
setattr(self._parent, attr, None)
- return no_content()
+ response.status = falcon.HTTP_204
diff --git a/src/mailman/rest/tests/test_preferences.py b/src/mailman/rest/tests/test_preferences.py
new file mode 100644
index 000000000..91a066cff
--- /dev/null
+++ b/src/mailman/rest/tests/test_preferences.py
@@ -0,0 +1,67 @@
+# Copyright (C) 2014 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/>.
+
+"""Test various preference functionality."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestPreferences',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.database.transaction import transaction
+from mailman.interfaces.usermanager import IUserManager
+from mailman.testing.helpers import call_api
+from mailman.testing.layers import RESTLayer
+from urllib2 import HTTPError
+from zope.component import getUtility
+
+
+class TestPreferences(unittest.TestCase):
+ """Test various preference functionality."""
+
+ layer = RESTLayer
+
+ def setUp(self):
+ user_manager = getUtility(IUserManager)
+ with transaction():
+ self._mlist = create_list('test@example.com')
+ anne = user_manager.create_address('anne@example.com')
+ self._member = self._mlist.subscribe(anne)
+
+ def test_read_only_member_all_preferences(self):
+ # A member's combined preferences are read-only.
+ with self.assertRaises(HTTPError) as cm:
+ call_api('http://localhost:9001/3.0/members/1/all/preferences', {
+ 'delivery_status': 'enabled',
+ }, method='PATCH')
+ # The resource at this endpoint doesn't even have a PATCH method.
+ self.assertEqual(cm.exception.code, 405)
+
+ def test_read_only_system_preferences(self):
+ # The system preferences are read-only.
+ with self.assertRaises(HTTPError) as cm:
+ call_api('http://localhost:9001/3.0/system/preferences', {
+ 'delivery_status': 'enabled',
+ }, method='PATCH')
+ # The resource at this endpoint doesn't even have a PATCH method.
+ self.assertEqual(cm.exception.code, 405)
diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py
index ca38d72dc..019d02aa7 100644
--- a/src/mailman/rest/users.py
+++ b/src/mailman/rest/users.py
@@ -185,7 +185,7 @@ class AUser(_UserBase):
user_manager.delete_user(self._user)
return no_content()
- @resource.child()
+ @child()
def preferences(self, request, segments):
"""/addresses/<email>/preferences"""
if len(segments) != 0: