summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen A. Goss2011-08-24 17:05:48 -0700
committerStephen A. Goss2011-08-24 17:05:48 -0700
commited21226dee1d139f6c8641f8253ed6eb51bbad10 (patch)
treee5dc3dd10e21213916a485babaea4f0d37af00bf
parent043562c695387a12e655997abf41cef77cb3d3a4 (diff)
downloadmailman-ed21226dee1d139f6c8641f8253ed6eb51bbad10.tar.gz
mailman-ed21226dee1d139f6c8641f8253ed6eb51bbad10.tar.zst
mailman-ed21226dee1d139f6c8641f8253ed6eb51bbad10.zip
LP 833132: add delivery_mode to member info in REST API, and make PATCHable with tests
-rw-r--r--src/mailman/rest/docs/addresses.txt5
-rw-r--r--src/mailman/rest/docs/membership.rst104
-rw-r--r--src/mailman/rest/members.py30
3 files changed, 129 insertions, 10 deletions
diff --git a/src/mailman/rest/docs/addresses.txt b/src/mailman/rest/docs/addresses.txt
index d82396e6b..71ab1f0f3 100644
--- a/src/mailman/rest/docs/addresses.txt
+++ b/src/mailman/rest/docs/addresses.txt
@@ -169,6 +169,7 @@ Elle can get her memberships for each of her email addresses.
... 'elle@example.com/memberships')
entry 0:
address: elle@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -176,6 +177,7 @@ Elle can get her memberships for each of her email addresses.
user: http://localhost:9001/3.0/users/2
entry 1:
address: elle@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: "..."
role: member
@@ -204,6 +206,7 @@ does not show up in the list of memberships for his other address.
... 'elle@example.com/memberships')
entry 0:
address: elle@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -211,6 +214,7 @@ does not show up in the list of memberships for his other address.
user: http://localhost:9001/3.0/users/2
entry 1:
address: elle@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: "..."
role: member
@@ -224,6 +228,7 @@ does not show up in the list of memberships for his other address.
... 'eperson@example.com/memberships')
entry 0:
address: eperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: "..."
role: member
diff --git a/src/mailman/rest/docs/membership.rst b/src/mailman/rest/docs/membership.rst
index bed4f425d..46c61631f 100644
--- a/src/mailman/rest/docs/membership.rst
+++ b/src/mailman/rest/docs/membership.rst
@@ -42,6 +42,7 @@ the REST interface.
>>> dump_json('http://localhost:9001/3.0/members')
entry 0:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -55,6 +56,7 @@ Bart's specific membership can be accessed directly:
>>> dump_json('http://localhost:9001/3.0/members/1')
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -68,6 +70,7 @@ the REST interface.
>>> dump_json('http://localhost:9001/3.0/members')
entry 0:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -75,6 +78,7 @@ the REST interface.
user: http://localhost:9001/3.0/users/1
entry 1:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -93,6 +97,7 @@ subscribes, she is returned first.
>>> dump_json('http://localhost:9001/3.0/members')
entry 0:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -100,6 +105,7 @@ subscribes, she is returned first.
user: http://localhost:9001/3.0/users/3
entry 1:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -107,6 +113,7 @@ subscribes, she is returned first.
user: http://localhost:9001/3.0/users/1
entry 2:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -129,6 +136,7 @@ User ids are different than member ids.
>>> dump_json('http://localhost:9001/3.0/members')
entry 0:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -136,6 +144,7 @@ User ids are different than member ids.
user: http://localhost:9001/3.0/users/3
entry 1:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -143,6 +152,7 @@ User ids are different than member ids.
user: http://localhost:9001/3.0/users/2
entry 2:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -150,6 +160,7 @@ User ids are different than member ids.
user: http://localhost:9001/3.0/users/3
entry 3:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -157,6 +168,7 @@ User ids are different than member ids.
user: http://localhost:9001/3.0/users/1
entry 4:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -172,6 +184,7 @@ We can also get just the members of a single mailing list.
... 'http://localhost:9001/3.0/lists/ant@example.com/roster/member')
entry 0:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -179,6 +192,7 @@ We can also get just the members of a single mailing list.
user: http://localhost:9001/3.0/users/3
entry 1:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -203,6 +217,7 @@ mailing list.
>>> dump_json('http://localhost:9001/3.0/members')
entry 0:
address: dperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: moderator
@@ -210,6 +225,7 @@ mailing list.
user: http://localhost:9001/3.0/users/4
entry 1:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -217,6 +233,7 @@ mailing list.
user: http://localhost:9001/3.0/users/3
entry 2:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -224,6 +241,7 @@ mailing list.
user: http://localhost:9001/3.0/users/2
entry 3:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: owner
@@ -231,6 +249,7 @@ mailing list.
user: http://localhost:9001/3.0/users/2
entry 4:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -238,6 +257,7 @@ mailing list.
user: http://localhost:9001/3.0/users/3
entry 5:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -245,6 +265,7 @@ mailing list.
user: http://localhost:9001/3.0/users/1
entry 6:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -260,6 +281,7 @@ We can access all the owners of a list.
... 'http://localhost:9001/3.0/lists/bee@example.com/roster/owner')
entry 0:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: owner
@@ -278,6 +300,7 @@ A specific member can always be referenced by their role and address.
>>> dump_json('http://localhost:9001/3.0/lists/'
... 'bee@example.com/owner/cperson@example.com')
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: owner
@@ -292,6 +315,7 @@ example, we can search for all the memberships of a particular address.
... })
entry 0:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -299,6 +323,7 @@ example, we can search for all the memberships of a particular address.
user: http://localhost:9001/3.0/users/3
entry 1:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -315,6 +340,7 @@ Or, we can find all the memberships for a particular mailing list.
... })
entry 0:
address: aperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -322,6 +348,7 @@ Or, we can find all the memberships for a particular mailing list.
user: http://localhost:9001/3.0/users/3
entry 1:
address: bperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -329,6 +356,7 @@ Or, we can find all the memberships for a particular mailing list.
user: http://localhost:9001/3.0/users/1
entry 2:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -336,12 +364,13 @@ Or, we can find all the memberships for a particular mailing list.
user: http://localhost:9001/3.0/users/2
entry 3:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: owner
self_link: http://localhost:9001/3.0/members/7
user: http://localhost:9001/3.0/users/2
- http_etag: "66836d0f23bed36fa9e0cda1e5dec7e5b0797743"
+ http_etag: "..."
start: 0
total_size: 4
@@ -354,6 +383,7 @@ list.
... })
entry 0:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -361,6 +391,7 @@ list.
user: http://localhost:9001/3.0/users/2
entry 1:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: owner
@@ -378,6 +409,7 @@ Or, we can find all the memberships for an address with a specific role.
... })
entry 0:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -385,6 +417,7 @@ Or, we can find all the memberships for an address with a specific role.
user: http://localhost:9001/3.0/users/2
entry 1:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -403,6 +436,7 @@ Finally, we can search for a specific member given all three criteria.
... })
entry 0:
address: cperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: ...
role: member
@@ -450,6 +484,7 @@ Elly is now a known user, and a member of the mailing list.
...
entry 3:
address: eperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: ...
role: member
@@ -487,6 +522,7 @@ list with her preferred address.
...
entry 4:
address: gwen@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -509,6 +545,7 @@ the new address.
...
entry 4:
address: gwen.person@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -565,7 +602,68 @@ Fred joins the `ant` mailing list but wants MIME digest delivery.
>>> memberships[0]
<Member: Fred Person <fperson@example.com>
on ant@example.com as MemberRole.member>
+ >>> print memberships[0].delivery_mode.enumname
+ mime_digests
+
+ >>> dump_json('http://localhost:9001/3.0/members/10')
+ address: fperson@example.com
+ delivery_mode: mime_digests
+ fqdn_listname: ant@example.com
+ http_etag: "..."
+ role: member
+ self_link: http://localhost:9001/3.0/members/10
+ user: http://localhost:9001/3.0/users/7
+Fred wants to change his delivery from MIME digest back to regular delivery.
+This can be done by PATCH'ing his member with the `delivery_mode`
+parameter.
+::
+
+ >>> transaction.abort()
+ >>> dump_json('http://localhost:9001/3.0/members/10', {
+ ... 'delivery_mode': 'regular',
+ ... }, method='PATCH')
+ content-length: 0
+ date: ...
+ server: ...
+ status: 204
+
+ >>> dump_json('http://localhost:9001/3.0/members/10')
+ address: fperson@example.com
+ delivery_mode: regular
+ fqdn_listname: ant@example.com
+ http_etag: "..."
+ role: member
+ self_link: http://localhost:9001/3.0/members/10
+ user: http://localhost:9001/3.0/users/7
+
+You can't PATCH a nonexistent member object.
+::
+
+ >>> dump_json('http://localhost:9001/3.0/members/99', {
+ ... 'delivery_mode': 'regular',
+ ... }, method='PATCH')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 404: 404 Not Found
+
+You can't PATCH a member with no attributes.
+::
+
+ >>> dump_json('http://localhost:9001/3.0/members/10', method='PATCH')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 400: 400 Bad Request
+
+You can't PATCH a member with anything other than `address` or `delivery_mode`.
+::
+
+ >>> dump_json('http://localhost:9001/3.0/members/10', {
+ ... 'powers': 'super',
+ ... }, method='PATCH')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 400: Unexpected parameters: powers
Changing delivery address
=========================
@@ -601,6 +699,7 @@ addresses.
...
entry 5:
address: herb@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -609,6 +708,7 @@ addresses.
...
entry 10:
address: herb@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: "..."
role: member
@@ -664,6 +764,7 @@ his membership ids have not changed.
... 'hperson@example.com/memberships')
entry 0:
address: hperson@example.com
+ delivery_mode: regular
fqdn_listname: ant@example.com
http_etag: "..."
role: member
@@ -671,6 +772,7 @@ his membership ids have not changed.
user: http://localhost:9001/3.0/users/8
entry 1:
address: hperson@example.com
+ delivery_mode: regular
fqdn_listname: bee@example.com
http_etag: "..."
role: member
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index 047c375bb..2ddd24dc9 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -59,6 +59,7 @@ class _MemberBase(resource.Resource, CollectionMixin):
role=role,
user=path_to('users/{0}'.format(member.user.user_id)),
self_link=path_to('members/{0}'.format(member.member_id)),
+ delivery_mode=member.delivery_mode,
)
def _get_collection(self, request):
@@ -124,17 +125,28 @@ class AMember(_MemberBase):
This is how subscription changes are done.
"""
- # Currently, only the `address` parameter can be patched.
- values = Validator(address=unicode)(request)
- assert len(values) == 1, 'Unexpected values'
- email = values['address']
- address = getUtility(IUserManager).get_address(email)
- if address is None:
- return http.bad_request([], b'Address not registered')
+ # Currently, only the `address` or `delivery_mode` parameters can be patched.
+ if self._member is None:
+ return http.not_found()
try:
- self._member.address = address
- except (MembershipError, UnverifiedAddressError) as error:
+ values = Validator(address=unicode,
+ delivery_mode=enum_validator(DeliveryMode),
+ _optional=('delivery_mode', 'address'))(request)
+ except ValueError as error:
return http.bad_request([], str(error))
+ if len(values) == 0:
+ return http.bad_request()
+ if 'address' in values:
+ email = values['address']
+ address = getUtility(IUserManager).get_address(email)
+ if address is None:
+ return http.bad_request([], b'Address not registered')
+ try:
+ self._member.address = address
+ except (MembershipError, UnverifiedAddressError) as error:
+ return http.bad_request([], str(error))
+ if 'delivery_mode' in values:
+ self._member.preferences.delivery_mode = values['delivery_mode']
return no_content()