diff options
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 9 | ||||
| -rw-r--r-- | src/mailman/rest/docs/lists.rst | 55 | ||||
| -rw-r--r-- | src/mailman/rest/lists.py | 16 | ||||
| -rw-r--r-- | src/mailman/rest/root.py | 6 |
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): |
