summaryrefslogtreecommitdiff
path: root/src/mailman/rest
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/rest')
-rw-r--r--src/mailman/rest/docs/__init__.py12
-rw-r--r--src/mailman/rest/plugins.py76
-rw-r--r--src/mailman/rest/root.py15
-rw-r--r--src/mailman/rest/tests/test_systemconf.py2
4 files changed, 95 insertions, 10 deletions
diff --git a/src/mailman/rest/docs/__init__.py b/src/mailman/rest/docs/__init__.py
index 350a6b83e..671ea38d6 100644
--- a/src/mailman/rest/docs/__init__.py
+++ b/src/mailman/rest/docs/__init__.py
@@ -19,22 +19,13 @@
import threading
+from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, HTTPServer
from mailman.testing.helpers import wait_for_webservice
from mailman.testing.layers import RESTLayer
from public import public
-# New in Python 3.5.
-try:
- from http import HTTPStatus
-except ImportError: # pragma: nocover
- class HTTPStatus:
- FORBIDDEN = 403
- NOT_FOUND = 404
- OK = 200
-
-
# We need a web server to vend non-mailman: urls.
class TestableHandler(BaseHTTPRequestHandler):
# Be quiet.
@@ -78,6 +69,7 @@ class HTTPLayer(RESTLayer):
cls._thread.join()
+# For flufl.testing -- define this doctest's layer.
public(layer=HTTPLayer)
diff --git a/src/mailman/rest/plugins.py b/src/mailman/rest/plugins.py
new file mode 100644
index 000000000..2d61d881c
--- /dev/null
+++ b/src/mailman/rest/plugins.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2010-2017 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""REST for plugins, dynamically proxies requests to plugin's rest_object."""
+
+from lazr.config import as_boolean
+from mailman.config import config
+from mailman.rest.helpers import CollectionMixin, NotFound, etag, okay
+from operator import itemgetter
+from public import public
+
+
+@public
+class AllPlugins(CollectionMixin):
+ """Read-only list of all plugin configs."""
+
+ def _resource_as_dict(self, plugin_config):
+ """See `CollectionMixin`."""
+ name, plugin_section = plugin_config
+ resource = {
+ 'name': name,
+ 'class': plugin_section['class'],
+ 'enabled': as_boolean(plugin_section['enabled']),
+ }
+ # Add the path to the plugin's own configuration file, if one was
+ # given.
+ plugin_config = plugin_section['configuration'].strip()
+ if len(plugin_config) > 0:
+ resource['configuration'] = plugin_config
+ return resource
+
+ def _get_collection(self, request):
+ """See `CollectionMixin`."""
+ # plugin_configs returns a 2-tuple of (name, section), so sort
+ # alphabetically on the plugin name.
+ return sorted(config.plugin_configs, key=itemgetter(0))
+
+ def on_get(self, request, response):
+ """/plugins"""
+ resource = self._make_collection(request)
+ okay(response, etag(resource))
+
+
+@public
+class APlugin:
+ """REST proxy to the plugin's rest_object."""
+
+ def __init__(self, plugin_name):
+ self._resource = None
+ if plugin_name in config.plugins:
+ plugin = config.plugins[plugin_name]
+ self._resource = plugin.resource
+ # If the plugin doesn't exist or doesn't provide a resource, just proxy
+ # to NotFound.
+ if self._resource is None:
+ self._resource = NotFound()
+
+ def __getattr__(self, attrib):
+ return getattr(self._resource, attrib)
+
+ def __dir__(self):
+ return dir(self._resource)
diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py
index 76289078b..46116aba6 100644
--- a/src/mailman/rest/root.py
+++ b/src/mailman/rest/root.py
@@ -30,6 +30,7 @@ from mailman.rest.helpers import (
BadRequest, NotFound, child, etag, no_content, not_found, okay)
from mailman.rest.lists import AList, AllLists, Styles
from mailman.rest.members import AMember, AllMembers, FindMembers
+from mailman.rest.plugins import APlugin, AllPlugins
from mailman.rest.preferences import ReadOnlyPreferences
from mailman.rest.queues import AQueue, AQueueFile, AllQueues
from mailman.rest.templates import TemplateFinder
@@ -308,6 +309,20 @@ class TopLevel:
return BadRequest(), []
@child()
+ def plugins(self, context, segments):
+ """/<api>/plugins
+ /<api>/plugins/<plugin_name>
+ /<api>/plugins/<plugin_name>/...
+ """
+ if self.api.version_info < (3, 1):
+ return NotFound(), []
+ if len(segments) == 0:
+ return AllPlugins(), []
+ else:
+ plugin_name = segments.pop(0)
+ return APlugin(plugin_name), segments
+
+ @child()
def bans(self, context, segments):
"""/<api>/bans
/<api>/bans/<email>
diff --git a/src/mailman/rest/tests/test_systemconf.py b/src/mailman/rest/tests/test_systemconf.py
index f9fe9caa0..91ee9befa 100644
--- a/src/mailman/rest/tests/test_systemconf.py
+++ b/src/mailman/rest/tests/test_systemconf.py
@@ -168,6 +168,7 @@ class TestSystemConfiguration(unittest.TestCase):
'logging.http',
'logging.locks',
'logging.mischief',
+ 'logging.plugins',
'logging.root',
'logging.runner',
'logging.smtp',
@@ -182,6 +183,7 @@ class TestSystemConfiguration(unittest.TestCase):
'paths.here',
'paths.local',
'paths.testing',
+ 'plugin.master',
'runner.archive',
'runner.bad',
'runner.bounces',