diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/interfaces/domain.py | 26 | ||||
| -rw-r--r-- | src/mailman/queue/docs/rest.txt | 7 | ||||
| -rw-r--r-- | src/mailman/rest/adapters.py | 7 | ||||
| -rw-r--r-- | src/mailman/rest/configuration.py | 3 | ||||
| -rw-r--r-- | src/mailman/rest/configure.zcml | 2 | ||||
| -rw-r--r-- | src/mailman/rest/docs/basic.txt | 4 | ||||
| -rw-r--r-- | src/mailman/rest/docs/domains.txt | 66 | ||||
| -rw-r--r-- | src/mailman/rest/docs/lists.txt | 2 | ||||
| -rw-r--r-- | src/mailman/tests/test_documentation.py | 19 |
9 files changed, 112 insertions, 24 deletions
diff --git a/src/mailman/interfaces/domain.py b/src/mailman/interfaces/domain.py index f9476fc3d..96ec1568d 100644 --- a/src/mailman/interfaces/domain.py +++ b/src/mailman/interfaces/domain.py @@ -29,7 +29,7 @@ __all__ = [ from lazr.restful.declarations import ( collection_default_content, export_as_webservice_collection, - export_as_webservice_entry, exported) + export_as_webservice_entry, export_factory_operation, exported) from zope.interface import Interface, Attribute from zope.schema import TextLine @@ -174,3 +174,27 @@ class IDomainCollection(Interface): :return: The list of all known domains. :rtype: list of `IDomain` """ + + @export_factory_operation( + IDomain, + ('email_host', 'description', 'base_url', 'contact_address')) + def new(email_host, description=None, base_url=None, contact_address=None): + """Add a new domain. + + :param email_host: The email host name for the domain. + :type email_host: string + :param description: The description of the domain. + :type description: string + :param base_url: The base url, including the scheme for the web + interface of the domain. If not given, it defaults to + http://`email_host`/ + :type base_url: string + :param contact_address: The email contact address for the human + managing the domain. If not given, defaults to + postmaster@`email_host` + :type contact_address: string + :return: The new domain object + :rtype: `IDomain` + :raises `BadDomainSpecificationError`: when the `email_host` is + already registered. + """ diff --git a/src/mailman/queue/docs/rest.txt b/src/mailman/queue/docs/rest.txt index 62e61643f..b46f0f304 100644 --- a/src/mailman/queue/docs/rest.txt +++ b/src/mailman/queue/docs/rest.txt @@ -1,3 +1,4 @@ +=========== REST server =========== @@ -13,11 +14,11 @@ The RESTful server can be used to access basic version information. http_etag: "..." mailman_version: GNU Mailman 3.0... (...) python_version: ... - resource_type_link: https://localhost:8001/3.0/#system - self_link: https://localhost:8001/3.0/system + resource_type_link: http://localhost:8001/3.0/#system + self_link: http://localhost:8001/3.0/system Clean up --------- +======== >>> master.stop() diff --git a/src/mailman/rest/adapters.py b/src/mailman/rest/adapters.py index 50ef89b18..4dcf23e54 100644 --- a/src/mailman/rest/adapters.py +++ b/src/mailman/rest/adapters.py @@ -61,3 +61,10 @@ class DomainCollection: if domain is None: raise NotFound(self, name) return domain + + def new(self, email_host, description=None, base_url=None, + contact_address=None): + """See `IDomainCollection`.""" + value = self._manager.add( + email_host, description, base_url, contact_address) + return value diff --git a/src/mailman/rest/configuration.py b/src/mailman/rest/configuration.py index 07debb617..1c7378010 100644 --- a/src/mailman/rest/configuration.py +++ b/src/mailman/rest/configuration.py @@ -25,6 +25,7 @@ __all__ = [ ] +from lazr.config import as_boolean from lazr.restful.interfaces import IWebServiceConfiguration from zope.interface import implements @@ -51,7 +52,7 @@ class AdminWebServiceConfiguration: @property def use_https(self): """See `IWebServiceConfiguration`.""" - return config.webservice.use_https + return as_boolean(config.webservice.use_https) # This should match the major.minor Mailman version. service_version_uri_prefix = '{0.MAJOR_REV}.{0.MINOR_REV}'.format(version) diff --git a/src/mailman/rest/configure.zcml b/src/mailman/rest/configure.zcml index 8b9d6fb70..79e8ba0e7 100644 --- a/src/mailman/rest/configure.zcml +++ b/src/mailman/rest/configure.zcml @@ -12,6 +12,8 @@ <webservice:register module="mailman.interfaces.listmanager" /> <webservice:register module="mailman.interfaces.system" /> + <adapter factory="zope.publisher.http.HTTPCharsets" /> + <adapter for="mailman.interfaces.domain.IDomainManager" provides="mailman.interfaces.domain.IDomainCollection" diff --git a/src/mailman/rest/docs/basic.txt b/src/mailman/rest/docs/basic.txt index 06a507def..79abbfde1 100644 --- a/src/mailman/rest/docs/basic.txt +++ b/src/mailman/rest/docs/basic.txt @@ -16,8 +16,8 @@ returned. http_etag: "..." mailman_version: GNU Mailman 3.0... (...) python_version: ... - resource_type_link: https://localhost:8001/3.0/#system - self_link: https://localhost:8001/3.0/system + resource_type_link: http://localhost:8001/3.0/#system + self_link: http://localhost:8001/3.0/system Non-existent links diff --git a/src/mailman/rest/docs/domains.txt b/src/mailman/rest/docs/domains.txt index db1fe7258..b486515cf 100644 --- a/src/mailman/rest/docs/domains.txt +++ b/src/mailman/rest/docs/domains.txt @@ -14,7 +14,7 @@ The REST API can be queried for the set of known domains, of which there are initially none. >>> dump_json('http://localhost:8001/3.0/domains') - resource_type_link: https://localhost:8001/3.0/#domains + resource_type_link: http://localhost:8001/3.0/#domains start: None total_size: 0 @@ -34,10 +34,10 @@ Once a domain is added though, it is accessible through the API. description: An example domain email_host: example.com http_etag: "..." - resource_type_link: https://localhost:8001/3.0/#domain - self_link: https://localhost:8001/3.0/domains/example.com + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/example.com url_host: lists.example.com - resource_type_link: https://localhost:8001/3.0/#domains + resource_type_link: http://localhost:8001/3.0/#domains start: 0 total_size: 1 @@ -64,8 +64,8 @@ At the top level, all domains are returned as separate entries. description: An example domain email_host: example.com http_etag: "..." - resource_type_link: https://localhost:8001/3.0/#domain - self_link: https://localhost:8001/3.0/domains/example.com + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/example.com url_host: lists.example.com entry 1: base_url: http://mail.example.org @@ -73,8 +73,8 @@ At the top level, all domains are returned as separate entries. description: None email_host: example.org http_etag: "..." - resource_type_link: https://localhost:8001/3.0/#domain - self_link: https://localhost:8001/3.0/domains/example.org + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/example.org url_host: mail.example.org entry 2: base_url: http://example.net @@ -82,10 +82,10 @@ At the top level, all domains are returned as separate entries. description: Porkmasters email_host: lists.example.net http_etag: "..." - resource_type_link: https://localhost:8001/3.0/#domain - self_link: https://localhost:8001/3.0/domains/lists.example.net + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/lists.example.net url_host: example.net - resource_type_link: https://localhost:8001/3.0/#domains + resource_type_link: http://localhost:8001/3.0/#domains start: 0 total_size: 3 @@ -102,8 +102,8 @@ self_links from the above collection. description: Porkmasters email_host: lists.example.net http_etag: "..." - resource_type_link: https://localhost:8001/3.0/#domain - self_link: https://localhost:8001/3.0/domains/lists.example.net + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/lists.example.net url_host: example.net But we get a 404 for a non-existent domain. @@ -112,3 +112,43 @@ But we get a 404 for a non-existent domain. Traceback (most recent call last): ... HTTPError: HTTP Error 404: Not Found + + +Creating new domains +==================== + +New domains can be created by posting to the 'domains' url. However +lazr.restful requires us to use a 'named operation' instead of posting +directly to the URL. + + >>> dump_json('http://localhost:8001/3.0/domains', { + ... 'ws.op': 'new', + ... 'email_host': 'lists.example.com', + ... }) + URL: http://localhost:8001/3.0/domains + content-length: 0 + content-type: text/plain + date: ... + location: http://localhost:8001/3.0/domains/lists.example.com + server: WSGIServer/... Python/... + x-content-type-warning: guessed from content + x-powered-by: Zope (www.zope.org), Python (www.python.org) + +Now the web service knows about our new domain. + + >>> dump_json('http://localhost:8001/3.0/domains/lists.example.com') + base_url: http://lists.example.com + contact_address: postmaster@lists.example.com + description: None + email_host: lists.example.com + http_etag: "349365fdbf946e64fc1052b936b9192eaa94b850" + resource_type_link: http://localhost:8001/3.0/#domain + self_link: http://localhost:8001/3.0/domains/lists.example.com + url_host: lists.example.com + +And the new domain is in our database. + + >>> manager['lists.example.com'] + <Domain lists.example.com, + base_url: http://lists.example.com, + contact_address: postmaster@lists.example.com> diff --git a/src/mailman/rest/docs/lists.txt b/src/mailman/rest/docs/lists.txt index 5cdf05639..64645e8e0 100644 --- a/src/mailman/rest/docs/lists.txt +++ b/src/mailman/rest/docs/lists.txt @@ -7,6 +7,6 @@ top level collection that can return all the mailing lists. There aren't any yet though. >>> dump_json('http://localhost:8001/3.0/lists') - resource_type_link: https://localhost:8001/3.0/#mailing_lists + resource_type_link: http://localhost:8001/3.0/#mailing_lists start: None total_size: 0 diff --git a/src/mailman/tests/test_documentation.py b/src/mailman/tests/test_documentation.py index 0409e737c..81762c5cc 100644 --- a/src/mailman/tests/test_documentation.py +++ b/src/mailman/tests/test_documentation.py @@ -37,6 +37,7 @@ import doctest import unittest from email import message_from_string +from urllib import urlencode from urllib2 import urlopen import mailman @@ -109,16 +110,28 @@ def dump_msgdata(msgdata, *additional_skips): print '{0:{2}}: {1}'.format(key, msgdata[key], longest) -def dump_json(url): +def dump_json(url, data=None): """Print the JSON dictionary read from a URL. :param url: The url to open, read, and print. :type url: string + :param data: Data to use to POST to a URL. + :type data: dict """ - fp = urlopen(url) + if data is None: + fp = urlopen(url) + else: + fp = urlopen(url, urlencode(data)) # fp does not support the context manager protocol. try: - data = json.load(fp) + raw_data = fp.read() + if len(raw_data) == 0: + print 'URL:', fp.geturl() + info = fp.info() + for header in sorted(info): + print '{0}: {1}'.format(header, info[header]) + return + data = json.loads(raw_data) finally: fp.close() for key in sorted(data): |
