summaryrefslogtreecommitdiff
path: root/src/mailman/rest
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/rest')
-rw-r--r--src/mailman/rest/docs/owners.rst89
-rw-r--r--src/mailman/rest/root.py10
-rw-r--r--src/mailman/rest/tests/test_owners.py40
-rw-r--r--src/mailman/rest/users.py15
4 files changed, 153 insertions, 1 deletions
diff --git a/src/mailman/rest/docs/owners.rst b/src/mailman/rest/docs/owners.rst
new file mode 100644
index 000000000..42be49c02
--- /dev/null
+++ b/src/mailman/rest/docs/owners.rst
@@ -0,0 +1,89 @@
+===============
+ Server owners
+===============
+
+Certain users can be designated as *server owners*. This role has no direct
+function in the core, but it can be used by clients of the REST API to
+determine additional permissions. For example, Postorius might allow server
+owners to create new domains.
+
+Initially, there are no server owners.
+
+ >>> dump_json('http://localhost:9001/3.0/owners')
+ http_etag: "..."
+ start: 0
+ total_size: 0
+
+When new users are created in the core, they do not become server owners by
+default.
+
+ >>> from zope.component import getUtility
+ >>> from mailman.interfaces.usermanager import IUserManager
+ >>> user_manager = getUtility(IUserManager)
+ >>> anne = user_manager.create_user('anne@example.com', 'Anne Person')
+ >>> transaction.commit()
+ >>> dump_json('http://localhost:9001/3.0/owners')
+ http_etag: "..."
+ start: 0
+ total_size: 0
+
+Anne's server owner flag is set.
+
+ >>> anne.is_server_owner = True
+ >>> transaction.commit()
+
+And now we can find her user record.
+
+ >>> dump_json('http://localhost:9001/3.0/owners')
+ entry 0:
+ created_on: 2005-08-01T07:49:23
+ display_name: Anne Person
+ http_etag: "..."
+ is_server_owner: True
+ self_link: http://localhost:9001/3.0/users/1
+ user_id: 1
+ http_etag: "..."
+ start: 0
+ total_size: 1
+
+Bart and Cate are also users, but not server owners.
+
+ >>> bart = user_manager.create_user('bart@example.com', 'Bart Person')
+ >>> cate = user_manager.create_user('cate@example.com', 'Cate Person')
+ >>> transaction.commit()
+ >>> dump_json('http://localhost:9001/3.0/owners')
+ entry 0:
+ created_on: 2005-08-01T07:49:23
+ display_name: Anne Person
+ http_etag: "..."
+ is_server_owner: True
+ self_link: http://localhost:9001/3.0/users/1
+ user_id: 1
+ http_etag: "..."
+ start: 0
+ total_size: 1
+
+Anne retires as a server owner, with Bart and Cate taking over.
+
+ >>> anne.is_server_owner = False
+ >>> bart.is_server_owner = True
+ >>> cate.is_server_owner = True
+ >>> transaction.commit()
+ >>> dump_json('http://localhost:9001/3.0/owners')
+ entry 0:
+ created_on: 2005-08-01T07:49:23
+ display_name: Bart Person
+ http_etag: "..."
+ is_server_owner: True
+ self_link: http://localhost:9001/3.0/users/2
+ user_id: 2
+ entry 1:
+ created_on: 2005-08-01T07:49:23
+ display_name: Cate Person
+ http_etag: "..."
+ is_server_owner: True
+ self_link: http://localhost:9001/3.0/users/3
+ user_id: 3
+ http_etag: "..."
+ start: 0
+ total_size: 2
diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py
index ca8bbc4a9..0682619b1 100644
--- a/src/mailman/rest/root.py
+++ b/src/mailman/rest/root.py
@@ -39,7 +39,7 @@ from mailman.rest.members import AMember, AllMembers, FindMembers
from mailman.rest.preferences import ReadOnlyPreferences
from mailman.rest.queues import AQueue, AQueueFile, AllQueues
from mailman.rest.templates import TemplateFinder
-from mailman.rest.users import AUser, AllUsers
+from mailman.rest.users import AUser, AllUsers, ServerOwners
from zope.component import getUtility
@@ -234,6 +234,14 @@ class TopLevel:
return AUser(user_id), segments
@child()
+ def owners(self, request, segments):
+ """/<api>/owners"""
+ if len(segments) != 0:
+ return BadRequest(), []
+ else:
+ return ServerOwners(), segments
+
+ @child()
def templates(self, request, segments):
"""/<api>/templates/<fqdn_listname>/<template>/[<language>]
diff --git a/src/mailman/rest/tests/test_owners.py b/src/mailman/rest/tests/test_owners.py
new file mode 100644
index 000000000..2cbebc5c4
--- /dev/null
+++ b/src/mailman/rest/tests/test_owners.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2015 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/>.
+
+"""Additional tests for the top-level owners resource."""
+
+__all__ = [
+ 'TestOwners',
+ ]
+
+
+import unittest
+
+from mailman.testing.helpers import call_api
+from mailman.testing.layers import RESTLayer
+from urllib.error import HTTPError
+
+
+
+class TestOwners(unittest.TestCase):
+ layer = RESTLayer
+
+ def test_bogus_trailing_path(self):
+ # Nothing is allowed after the top-level /owners resource.
+ with self.assertRaises(HTTPError) as cm:
+ call_api('http://localhost:9001/3.0/owners/anne')
+ self.assertEqual(cm.exception.code, 400)
diff --git a/src/mailman/rest/users.py b/src/mailman/rest/users.py
index 252e7757b..6c352fd8c 100644
--- a/src/mailman/rest/users.py
+++ b/src/mailman/rest/users.py
@@ -464,3 +464,18 @@ class OwnersForDomain(_UserBase):
def _get_collection(self, request):
"""See `CollectionMixin`."""
return list(self._domain.owners)
+
+
+
+class ServerOwners(_UserBase):
+ """All server owners."""
+
+ def on_get(self, request, response):
+ """/owners"""
+ resource = self._make_collection(request)
+ okay(response, etag(resource))
+
+ @paginate
+ def _get_collection(self, request):
+ """See `CollectionMixin`."""
+ return list(getUtility(IUserManager).server_owners)