summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2015-02-26 15:50:37 -0500
committerSimo Sorce <simo@redhat.com>2015-02-27 16:05:49 -0500
commit7957f8d19d6693de52c758cad76cd61480ec336f (patch)
tree2699c54ee08a54df7cf302e4278b93673ca0d013
parent075c3c53f72fde8e18af3f505249bef8812b7da3 (diff)
downloadipsilon-7957f8d19d6693de52c758cad76cd61480ec336f.tar.gz
ipsilon-7957f8d19d6693de52c758cad76cd61480ec336f.tar.xz
ipsilon-7957f8d19d6693de52c758cad76cd61480ec336f.zip
Add base REST provider framework classes
These classes handle mounting the REST plugins. The starting mount point is: /idp/rest/providers https://fedorahosted.org/ipsilon/ticket/26 Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
-rw-r--r--ipsilon/providers/common.py41
-rw-r--r--ipsilon/rest/__init__.py0
-rw-r--r--ipsilon/rest/common.py89
-rw-r--r--ipsilon/rest/providers.py11
4 files changed, 141 insertions, 0 deletions
diff --git a/ipsilon/providers/common.py b/ipsilon/providers/common.py
index 4206387..dff302d 100644
--- a/ipsilon/providers/common.py
+++ b/ipsilon/providers/common.py
@@ -19,6 +19,7 @@ from ipsilon.util.log import Log
from ipsilon.util.plugin import PluginInstaller, PluginLoader
from ipsilon.util.plugin import PluginObject, PluginConfig
from ipsilon.util.page import Page
+from ipsilon.rest.common import RestPage
import cherrypy
@@ -153,3 +154,43 @@ class ProvidersInstall(object):
def __init__(self):
pi = PluginInstaller(ProvidersInstall, FACILITY)
self.plugins = pi.get_plugins()
+
+
+class RestProviderBase(RestPage):
+
+ def __init__(self, site, config):
+ super(RestProviderBase, self).__init__(site)
+ self.plugin_name = config.name
+ self.cfg = config
+
+ def GET(self, *args, **kwargs):
+ raise cherrypy.HTTPError(501)
+
+ def POST(self, *args, **kwargs):
+ raise cherrypy.HTTPError(501)
+
+ def DELETE(self, *args, **kwargs):
+ raise cherrypy.HTTPError(501)
+
+ def PUT(self, *args, **kwargs):
+ raise cherrypy.HTTPError(501)
+
+ def root(self, *args, **kwargs):
+ method = cherrypy.request.method
+
+ preop = getattr(self, 'pre_%s' % method, None)
+ if preop and callable(preop):
+ preop(*args, **kwargs)
+
+ op = getattr(self, method, self.GET)
+ if callable(op):
+ return op(*args, **kwargs)
+ else:
+ raise cherrypy.HTTPError(405)
+
+ def _debug(self, fact):
+ superfact = '%s: %s' % (self.plugin_name, fact)
+ super(RestProviderBase, self)._debug(superfact)
+
+ def _audit(self, fact):
+ cherrypy.log('%s: %s' % (self.plugin_name, fact))
diff --git a/ipsilon/rest/__init__.py b/ipsilon/rest/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ipsilon/rest/__init__.py
diff --git a/ipsilon/rest/common.py b/ipsilon/rest/common.py
new file mode 100644
index 0000000..4103e8e
--- /dev/null
+++ b/ipsilon/rest/common.py
@@ -0,0 +1,89 @@
+# Copyright (C) 2015 Ipsilon Contributors see COPYING for license
+
+import cherrypy
+import json
+from functools import wraps
+from ipsilon.util.endpoint import Endpoint
+
+
+def jsonout(func):
+ """
+ JSON output decorator. Does not handle binary data.
+ """
+ @wraps(func)
+ def wrapper(*args, **kw):
+ value = func(*args, **kw)
+ cherrypy.response.headers["Content-Type"] = \
+ "application/json;charset=utf-8"
+ return json.dumps(value, sort_keys=True, indent=2)
+
+ return wrapper
+
+
+def rest_error(status=500, message=''):
+ """
+ Create a REST error response.
+
+ The assumption is that the jsonout wrapper will handle converting
+ the response to JSON.
+ """
+ cherrypy.response.status = status
+ cherrypy.response.headers['Content-Type'] = 'application/json'
+ return {'status': status, 'message': message}
+
+
+class RestPage(Endpoint):
+
+ def __init__(self, *args, **kwargs):
+ super(RestPage, self).__init__(*args, **kwargs)
+ self.default_headers.update({
+ 'Cache-Control': 'no-cache, must-revalidate',
+ 'Pragma': 'no-cache',
+ 'Expires': 'Thu, 01 Dec 1994 16:00:00 GMT',
+ })
+ self.auth_protect = True
+
+
+class RestPlugins(RestPage):
+ def __init__(self, name, site, parent, facility, ordered=True):
+ super(RestPlugins, self).__init__(site)
+ self._master = parent
+ self.name = name
+ self.title = '%s plugins' % name
+ self.url = '%s/%s' % (parent.url, name)
+ self.facility = facility
+ self.template = None
+ self.order = None
+ parent.add_subtree(name, self)
+
+ for plugin in self._site[facility].available:
+ obj = self._site[facility].available[plugin]
+ if hasattr(obj, 'rest'):
+ cherrypy.log.error('Rest plugin: %s' % plugin)
+ obj.rest.mount(self)
+
+ def root_with_msg(self, message=None, message_type=None, changed=None):
+ return None
+
+ def root(self, *args, **kwargs):
+ return self.root_with_msg()
+
+
+class Rest(RestPage):
+
+ def __init__(self, site, mount):
+ super(Rest, self).__init__(site)
+ self.title = None
+ self.mount = mount
+ self.url = '%s/%s' % (self.basepath, mount)
+ self.menu = [self]
+
+ @jsonout
+ def root(self, *args, **kwargs):
+ return rest_error(404, 'Not Found')
+
+ def add_subtree(self, name, page):
+ self.__dict__[name] = page
+
+ def del_subtree(self, name):
+ del self.__dict__[name]
diff --git a/ipsilon/rest/providers.py b/ipsilon/rest/providers.py
new file mode 100644
index 0000000..b32efc5
--- /dev/null
+++ b/ipsilon/rest/providers.py
@@ -0,0 +1,11 @@
+# Copyright (C) 2015 Ipsilon Contributors see COPYING for license
+
+from ipsilon.rest.common import RestPlugins
+from ipsilon.providers.common import FACILITY
+
+
+class RestProviderPlugins(RestPlugins):
+ def __init__(self, site, parent):
+ super(RestProviderPlugins, self).__init__('providers', site, parent,
+ FACILITY, ordered=False)
+ self.title = 'Identity Providers'