diff options
| author | Barry Warsaw | 2014-08-13 00:18:23 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2014-08-13 00:18:23 -0400 |
| commit | 72dd28e26b1fa369de93652bd51869cebd79c0a3 (patch) | |
| tree | 5a01056497024f280141e78f8e1a81b22c298fad | |
| parent | bc4e33da9a97df35d147e58535358b2468cd1cc8 (diff) | |
| download | mailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.tar.gz mailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.tar.zst mailman-72dd28e26b1fa369de93652bd51869cebd79c0a3.zip | |
| -rw-r--r-- | src/mailman/rest/addresses.py | 2 | ||||
| -rw-r--r-- | src/mailman/rest/docs/preferences.rst | 20 | ||||
| -rw-r--r-- | src/mailman/rest/members.py | 8 | ||||
| -rw-r--r-- | src/mailman/rest/preferences.py | 30 | ||||
| -rw-r--r-- | src/mailman/rest/tests/test_preferences.py | 67 | ||||
| -rw-r--r-- | src/mailman/rest/users.py | 2 |
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: |
