Barry Warsaw pushed to branch master at mailman / Mailman

Commits:
9c9d0f01 by Aurélien Bompard at 2015-12-08T10:20:22Z
Allow a Member's moderation_action to be changed by the REST API.

Cleanups by Barry.  Closes !67

- - - - -


5 changed files:

- src/mailman/docs/NEWS.rst
- src/mailman/rest/docs/addresses.rst
- src/mailman/rest/docs/membership.rst
- src/mailman/rest/members.py
- src/mailman/rest/tests/test_membership.py


Changes:

=====================================
src/mailman/docs/NEWS.rst
=====================================
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -113,6 +113,8 @@ REST
  * JSON representations for held message now include a ``self_link``.
  * When ``[devmode]enabled`` is set, the JSON output is sorted.  Given by
    Aurélien Bompard.
+ * A member's moderation action can be changed via the REST API.  Given by
+   Aurélien Bompard.
 
 Other
 -----


=====================================
src/mailman/rest/docs/addresses.rst
=====================================
--- a/src/mailman/rest/docs/addresses.rst
+++ b/src/mailman/rest/docs/addresses.rst
@@ -379,6 +379,7 @@ Elle can get her memberships for each of her email 
addresses.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/4
@@ -389,6 +390,7 @@ Elle can get her memberships for each of her email 
addresses.
         http_etag: "..."
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/4
@@ -420,6 +422,7 @@ does not show up in the list of memberships for his other 
address.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/4
@@ -430,6 +433,7 @@ does not show up in the list of memberships for his other 
address.
         http_etag: "..."
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/4
@@ -446,6 +450,7 @@ does not show up in the list of memberships for his other 
address.
         http_etag: "..."
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/4


=====================================
src/mailman/rest/docs/membership.rst
=====================================
--- a/src/mailman/rest/docs/membership.rst
+++ b/src/mailman/rest/docs/membership.rst
@@ -50,6 +50,7 @@ the REST interface.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -66,6 +67,7 @@ Bart's specific membership can be accessed directly:
     http_etag: ...
     list_id: bee.example.com
     member_id: 1
+    moderation_action: defer
     role: member
     self_link: http://localhost:9001/3.0/members/1
     user: http://localhost:9001/3.0/users/1
@@ -86,6 +88,7 @@ the REST interface.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -96,6 +99,7 @@ the REST interface.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -119,6 +123,7 @@ subscribes, she is returned first.
         http_etag: ...
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/3
@@ -129,6 +134,7 @@ subscribes, she is returned first.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -139,6 +145,7 @@ subscribes, she is returned first.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -168,6 +175,7 @@ User ids are different than member ids.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -178,6 +186,7 @@ User ids are different than member ids.
         http_etag: ...
         list_id: ant.example.com
         member_id: 5
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/5
         user: http://localhost:9001/3.0/users/2
@@ -188,6 +197,7 @@ User ids are different than member ids.
         http_etag: ...
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/3
@@ -198,6 +208,7 @@ User ids are different than member ids.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -208,6 +219,7 @@ User ids are different than member ids.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -226,6 +238,7 @@ We can also get just the members of a single mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -236,6 +249,7 @@ We can also get just the members of a single mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 5
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/5
         user: http://localhost:9001/3.0/users/2
@@ -262,6 +276,7 @@ page.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -280,6 +295,7 @@ This works with members of a single list as well as with 
all members.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -326,6 +342,7 @@ mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 6
+        moderation_action: accept
         role: moderator
         self_link: http://localhost:9001/3.0/members/6
         user: http://localhost:9001/3.0/users/4
@@ -336,6 +353,7 @@ mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -346,6 +364,7 @@ mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 5
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/5
         user: http://localhost:9001/3.0/users/2
@@ -356,6 +375,7 @@ mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 7
+        moderation_action: accept
         role: owner
         self_link: http://localhost:9001/3.0/members/7
         user: http://localhost:9001/3.0/users/2
@@ -366,6 +386,7 @@ mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/3
@@ -376,6 +397,7 @@ mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -386,6 +408,7 @@ mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -404,6 +427,7 @@ We can access all the owners of a list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 7
+        moderation_action: accept
         role: owner
         self_link: http://localhost:9001/3.0/members/7
         user: http://localhost:9001/3.0/users/2
@@ -425,6 +449,7 @@ A specific member can always be referenced by their role 
and address.
     http_etag: ...
     list_id: bee.example.com
     member_id: 7
+    moderation_action: accept
     role: owner
     self_link: http://localhost:9001/3.0/members/7
     user: http://localhost:9001/3.0/users/2
@@ -442,6 +467,7 @@ example, we can search for all the memberships of a 
particular address.
         http_etag: ...
         list_id: ant.example.com
         member_id: 4
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/4
         user: http://localhost:9001/3.0/users/3
@@ -452,6 +478,7 @@ example, we can search for all the memberships of a 
particular address.
         http_etag: ...
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/3
@@ -471,6 +498,7 @@ Or, we can find all the memberships for a particular 
mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 3
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/3
         user: http://localhost:9001/3.0/users/3
@@ -481,6 +509,7 @@ Or, we can find all the memberships for a particular 
mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 1
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/1
         user: http://localhost:9001/3.0/users/1
@@ -491,6 +520,7 @@ Or, we can find all the memberships for a particular 
mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -501,6 +531,7 @@ Or, we can find all the memberships for a particular 
mailing list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 7
+        moderation_action: accept
         role: owner
         self_link: http://localhost:9001/3.0/members/7
         user: http://localhost:9001/3.0/users/2
@@ -522,6 +553,7 @@ list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -532,6 +564,7 @@ list.
         http_etag: ...
         list_id: bee.example.com
         member_id: 7
+        moderation_action: accept
         role: owner
         self_link: http://localhost:9001/3.0/members/7
         user: http://localhost:9001/3.0/users/2
@@ -552,6 +585,7 @@ Or, we can find all the memberships for an address with a 
specific role.
         http_etag: ...
         list_id: ant.example.com
         member_id: 5
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/5
         user: http://localhost:9001/3.0/users/2
@@ -562,6 +596,7 @@ Or, we can find all the memberships for an address with a 
specific role.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -583,6 +618,7 @@ Finally, we can search for a specific member given all 
three criteria.
         http_etag: ...
         list_id: bee.example.com
         member_id: 2
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/2
         user: http://localhost:9001/3.0/users/2
@@ -636,6 +672,7 @@ Elly is now a known user, and a member of the mailing list.
         http_etag: ...
         list_id: ant.example.com
         member_id: 8
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/8
         user: http://localhost:9001/3.0/users/5
@@ -682,6 +719,7 @@ list with her preferred address.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 9
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/9
         user: http://localhost:9001/3.0/users/6
@@ -707,6 +745,7 @@ the new address.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 9
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/9
         user: http://localhost:9001/3.0/users/6
@@ -774,6 +813,7 @@ addresses.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 10
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/10
         user: http://localhost:9001/3.0/users/7
@@ -785,6 +825,7 @@ addresses.
         http_etag: "..."
         list_id: bee.example.com
         member_id: 11
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/11
         user: http://localhost:9001/3.0/users/7
@@ -843,6 +884,7 @@ his membership ids have not changed.
         http_etag: "..."
         list_id: ant.example.com
         member_id: 10
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/10
         user: http://localhost:9001/3.0/users/7
@@ -853,9 +895,38 @@ his membership ids have not changed.
         http_etag: "..."
         list_id: bee.example.com
         member_id: 11
+        moderation_action: defer
         role: member
         self_link: http://localhost:9001/3.0/members/11
         user: http://localhost:9001/3.0/users/7
     http_etag: "..."
     start: 0
     total_size: 2
+
+
+Moderating a member
+===================
+
+The moderation action for a member can be changed by PATCH'ing the
+`moderation_action` attribute.
+::
+
+    >>> dump_json('http://localhost:9001/3.0/members/10')
+    address: http://localhost:9001/3.0/addresses/hper...@example.com
+    ...
+    moderation_action: defer
+    ...
+
+    >>> dump_json('http://localhost:9001/3.0/members/10', {
+    ...           'moderation_action': 'hold',
+    ...           }, method='PATCH')
+    content-length: 0
+    date: ...
+    server: ...
+    status: 204
+
+    >>> dump_json('http://localhost:9001/3.0/members/10')
+    address: http://localhost:9001/3.0/addresses/hper...@example.com
+    ...
+    moderation_action: hold
+    ...


=====================================
src/mailman/rest/members.py
=====================================
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -26,6 +26,7 @@ __all__ = [
 
 
 from mailman.app.membership import add_member, delete_member
+from mailman.interfaces.action import Action
 from mailman.interfaces.address import IAddress, InvalidEmailAddressError
 from mailman.interfaces.listmanager import IListManager
 from mailman.interfaces.member import (
@@ -62,13 +63,14 @@ class _MemberBase(CollectionMixin):
         # URL.
         member_id = member.member_id.int
         response = dict(
-            list_id=member.list_id,
-            email=member.address.email,
-            role=role,
             address=self.path_to('addresses/{}'.format(member.address.email)),
-            self_link=self.path_to('members/{}'.format(member_id)),
             delivery_mode=member.delivery_mode,
+            email=member.address.email,
+            list_id=member.list_id,
             member_id=member_id,
+            moderation_action=member.moderation_action,
+            role=role,
+            self_link=self.path_to('members/{}'.format(member_id)),
             )
         # Add the user link if there is one.
         user = member.user
@@ -178,7 +180,9 @@ class AMember(_MemberBase):
             values = Validator(
                 address=str,
                 delivery_mode=enum_validator(DeliveryMode),
-                _optional=('address', 'delivery_mode'))(request)
+                moderation_action=enum_validator(Action),
+                _optional=('address', 'delivery_mode', 'moderation_action'),
+                )(request)
         except ValueError as error:
             bad_request(response, str(error))
             return
@@ -195,6 +199,8 @@ class AMember(_MemberBase):
                 return
         if 'delivery_mode' in values:
             self._member.preferences.delivery_mode = values['delivery_mode']
+        if 'moderation_action' in values:
+            self._member.moderation_action = values['moderation_action']
         no_content(response)
 
 


=====================================
src/mailman/rest/tests/test_membership.py
=====================================
--- a/src/mailman/rest/tests/test_membership.py
+++ b/src/mailman/rest/tests/test_membership.py
@@ -253,6 +253,19 @@ class TestMembership(unittest.TestCase):
             call_api('http://localhost:9001/3.0/members/1/all')
         self.assertEqual(cm.exception.code, 404)
 
+    def test_patch_member_invalid_moderation_action(self):
+        # /members/<id> PATCH with invalid 'moderation_action' returns 400.
+        with transaction():
+            anne = self._usermanager.create_address('a...@example.com')
+            self._mlist.subscribe(anne)
+        with self.assertRaises(HTTPError) as cm:
+            call_api('http://localhost:9001/3.0/members/1', {
+                     'moderation_action': 'invalid',
+                     }, method='PATCH')
+        self.assertEqual(cm.exception.code, 400)
+        self.assertEqual(cm.exception.reason,
+                         b'Cannot convert parameters: moderation_action')
+
 
 
 class CustomLayer(ConfigLayer):



View it on GitLab: 
https://gitlab.com/mailman/mailman/commit/9c9d0f01f8f5dff5ec5a83b953be81edf81566be
_______________________________________________
Mailman-checkins mailing list
Mailman-checkins@python.org
Unsubscribe: 
https://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to