summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2012-09-22 11:16:26 -0400
committerBarry Warsaw2012-09-22 11:16:26 -0400
commita8e5f267b418cd4bb577ae229fd7e22d5720e93f (patch)
treecff784535bce7134407d1ece7f94fd9b9f74a1ee
parentd20bb305a007f156ded813f5823fcf7ded66075b (diff)
parent8271738ba287c4688173ff760118996c1590b84f (diff)
downloadmailman-a8e5f267b418cd4bb577ae229fd7e22d5720e93f.tar.gz
mailman-a8e5f267b418cd4bb577ae229fd7e22d5720e93f.tar.zst
mailman-a8e5f267b418cd4bb577ae229fd7e22d5720e93f.zip
-rw-r--r--src/mailman/docs/NEWS.rst9
-rw-r--r--src/mailman/rest/docs/lists.rst55
-rw-r--r--src/mailman/rest/lists.py16
-rw-r--r--src/mailman/rest/root.py6
4 files changed, 69 insertions, 17 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 329264e31..984e0d9fb 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -12,6 +12,15 @@ Here is a history of user visible changes to Mailman.
==========================
(2012-XX-XX)
+REST
+----
+ * Add list_id to JSON representation for a mailing list (given by Jimmy
+ Bergman).
+ * The canonical resource for a mailing list (and thus its self_link) is now
+ the URL with the list-id. To reference a mailing list, the list-id url is
+ preferred, but for backward compatibility, the posting address is still
+ accepted.
+
3.0 beta 2 -- "Freeze"
======================
diff --git a/src/mailman/rest/docs/lists.rst b/src/mailman/rest/docs/lists.rst
index 610244968..0c4bbc419 100644
--- a/src/mailman/rest/docs/lists.rst
+++ b/src/mailman/rest/docs/lists.rst
@@ -23,10 +23,11 @@ Create a mailing list in a domain and it's accessible via the API.
display_name: Test-one
fqdn_listname: test-one@example.com
http_etag: "..."
+ list_id: test-one.example.com
list_name: test-one
mail_host: example.com
member_count: 0
- self_link: http://localhost:9001/3.0/lists/test-one@example.com
+ self_link: http://localhost:9001/3.0/lists/test-one.example.com
volume: 1
http_etag: "..."
start: 0
@@ -40,10 +41,11 @@ You can also query for lists from a particular domain.
display_name: Test-one
fqdn_listname: test-one@example.com
http_etag: "..."
+ list_id: test-one.example.com
list_name: test-one
mail_host: example.com
member_count: 0
- self_link: http://localhost:9001/3.0/lists/test-one@example.com
+ self_link: http://localhost:9001/3.0/lists/test-one.example.com
volume: 1
http_etag: "..."
start: 0
@@ -66,7 +68,7 @@ New mailing lists can also be created through the API, by posting to the
... })
content-length: 0
date: ...
- location: http://localhost:9001/3.0/lists/test-two@example.com
+ location: http://localhost:9001/3.0/lists/test-two.example.com
...
The mailing list exists in the database.
@@ -85,14 +87,31 @@ The mailing list exists in the database.
It is also available via the location given in the response.
+ >>> dump_json('http://localhost:9001/3.0/lists/test-two.example.com')
+ display_name: Test-two
+ fqdn_listname: test-two@example.com
+ http_etag: "..."
+ list_id: test-two.example.com
+ list_name: test-two
+ mail_host: example.com
+ member_count: 0
+ self_link: http://localhost:9001/3.0/lists/test-two.example.com
+ volume: 1
+
+Normally, you access the list via its RFC 2369 list-id as shown above, but for
+backward compatibility purposes, you can also access it via the list's posting
+address, if that has never been changed (since the list-id is immutable, but
+the posting address is not).
+
>>> dump_json('http://localhost:9001/3.0/lists/test-two@example.com')
display_name: Test-two
fqdn_listname: test-two@example.com
http_etag: "..."
+ list_id: test-two.example.com
list_name: test-two
mail_host: example.com
member_count: 0
- self_link: http://localhost:9001/3.0/lists/test-two@example.com
+ self_link: http://localhost:9001/3.0/lists/test-two.example.com
volume: 1
However, you are not allowed to create a mailing list in a domain that does
@@ -122,34 +141,48 @@ Existing mailing lists can be deleted through the API, by doing an HTTP
``DELETE`` on the mailing list URL.
::
- >>> dump_json('http://localhost:9001/3.0/lists/test-two@example.com',
+ >>> dump_json('http://localhost:9001/3.0/lists/test-two.example.com',
... method='DELETE')
content-length: 0
date: ...
server: ...
status: 204
- # The above starts a Storm transaction, which will lock the database
- # unless we abort it.
- >>> transaction.abort()
-
The mailing list does not exist.
>>> print list_manager.get('test-two@example.com')
None
+ # Unlock the database.
+ >>> transaction.abort()
+
You cannot delete a mailing list that does not exist or has already been
deleted.
::
- >>> dump_json('http://localhost:9001/3.0/lists/test-two@example.com',
+ >>> dump_json('http://localhost:9001/3.0/lists/test-two.example.com',
... method='DELETE')
Traceback (most recent call last):
...
HTTPError: HTTP Error 404: 404 Not Found
- >>> dump_json('http://localhost:9001/3.0/lists/test-ten@example.com',
+ >>> dump_json('http://localhost:9001/3.0/lists/test-ten.example.com',
... method='DELETE')
Traceback (most recent call last):
...
HTTPError: HTTP Error 404: 404 Not Found
+
+For backward compatibility purposes, you can delete a list via its posting
+address as well.
+
+ >>> dump_json('http://localhost:9001/3.0/lists/test-one@example.com',
+ ... method='DELETE')
+ content-length: 0
+ date: ...
+ server: ...
+ status: 204
+
+The mailing list does not exist.
+
+ >>> print list_manager.get('test-one@example.com')
+ None
diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py
index f25133211..4e9de6905 100644
--- a/src/mailman/rest/lists.py
+++ b/src/mailman/rest/lists.py
@@ -107,11 +107,12 @@ class _ListBase(resource.Resource, CollectionMixin):
return dict(
display_name=mlist.display_name,
fqdn_listname=mlist.fqdn_listname,
+ list_id=mlist.list_id,
list_name=mlist.list_name,
mail_host=mlist.mail_host,
member_count=mlist.members.member_count,
volume=mlist.volume,
- self_link=path_to('lists/{0}'.format(mlist.fqdn_listname)),
+ self_link=path_to('lists/{0}'.format(mlist.list_id)),
)
def _get_collection(self, request):
@@ -122,8 +123,15 @@ class _ListBase(resource.Resource, CollectionMixin):
class AList(_ListBase):
"""A mailing list."""
- def __init__(self, list_name):
- self._mlist = getUtility(IListManager).get(list_name)
+ def __init__(self, list_identifier):
+ # list-id is preferred, but for backward compatibility, fqdn_listname
+ # is also accepted. If the string contains '@', treat it as the
+ # latter.
+ manager = getUtility(IListManager)
+ if '@' in list_identifier:
+ self._mlist = manager.get(list_identifier)
+ else:
+ self._mlist = manager.get_by_list_id(list_identifier)
@resource.GET()
def mailing_list(self, request):
@@ -192,7 +200,7 @@ class AllLists(_ListBase):
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.fqdn_listname))
+ location = path_to('lists/{0}'.format(mlist.list_id))
# Include no extra headers or body.
return http.created(location, [], None)
diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py
index 8c1a31cf2..ea1650e75 100644
--- a/src/mailman/rest/root.py
+++ b/src/mailman/rest/root.py
@@ -123,8 +123,10 @@ class TopLevel(resource.Resource):
if len(segments) == 0:
return AllLists()
else:
- list_name = segments.pop(0)
- return AList(list_name), segments
+ # list-id is preferred, but for backward compatibility,
+ # fqdn_listname is also accepted.
+ list_identifier = segments.pop(0)
+ return AList(list_identifier), segments
@resource.child()
def members(self, request, segments):