Implement GET and POST REST API for Service Providers
authorRob Crittenden <rcritten@redhat.com>
Thu, 26 Feb 2015 20:57:20 +0000 (15:57 -0500)
committerSimo Sorce <simo@redhat.com>
Fri, 27 Feb 2015 21:10:51 +0000 (16:10 -0500)
The mount point is /idp/rest/providers/saml2/SPS.

GET .../SPS will retrieve all Service Providers
GET .../SPS/foo will retrieve the Service Provider named foo
POST .../SPS/foo will create the Service Provider named foo

https://fedorahosted.org/ipsilon/ticket/26

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
ipsilon/providers/saml2/rest.py [new file with mode: 0644]

diff --git a/ipsilon/providers/saml2/rest.py b/ipsilon/providers/saml2/rest.py
new file mode 100644 (file)
index 0000000..6ad8ae6
--- /dev/null
@@ -0,0 +1,107 @@
+# Copyright (C) 2015  Ipsilon project Contributors, for licensee see COPYING
+
+import cherrypy
+from ipsilon.providers.common import RestProviderBase
+from ipsilon.providers.common import FACILITY
+from ipsilon.rest.common import rest_error, jsonout
+from ipsilon.providers.saml2.provider import ServiceProviderCreator
+from ipsilon.providers.saml2.provider import InvalidProviderId
+from lasso import ServerAddProviderFailedError
+
+
+class Saml2RestBase(RestProviderBase):
+    """
+    The root for REST pages.
+
+    Add new REST classes to this via add_subtree().
+    """
+
+    def __init__(self, site, config):
+        super(Saml2RestBase, self).__init__(site, config)
+        self.name = 'saml2'
+        self.cfg = config
+        self.url = None
+
+    def mount(self, page):
+        self.url = page.url
+        self.add_subtree('SPS', SPS(self._site, self))
+        page.add_subtree(self.name, self)
+
+
+class SPS(RestProviderBase):
+    """
+    REST interface for Service Providers
+    """
+
+    def __init__(self, site, parent):
+        super(SPS, self).__init__(site, parent)
+
+        self.parent = parent
+        self.backurl = parent.url
+        self.url = '%s/SPS' % (parent.url,)
+
+    def __get_idp(self):
+        """
+        Return the identity provider object
+        """
+        return self._site[FACILITY].available[self.parent.plugin_name]
+
+    def _get_sp(self, *args, **kwargs):
+        """
+        If PATH_INFO contains a value then get that value as the name of
+        the SP, otherwise return a list of all available SPs.
+        """
+        if len(args) > 0:
+            instance = args[0]
+        else:
+            instance = None
+
+        idp = self.__get_idp()
+
+        results = list()
+
+        if instance is not None:
+            data = idp.get_data(name='name', value=instance)
+            if len(data) == 0:
+                return rest_error(404, 'Provider %s not found' % instance)
+            idval = data.keys()[0]
+            data = idp.get_data(idval=idval)
+        else:
+            data = idp.get_data()
+
+        for idval in data.keys():
+            result = dict(provider=data[idval].get('name'),
+                          metadata=data[idval].get('metadata'),)
+            results.append(result)
+
+        return dict(result=results)
+
+    @jsonout
+    def GET(self, *args, **kwargs):
+        return self._get_sp(*args, **kwargs)
+
+    @jsonout
+    def POST(self, *args, **kwargs):
+        cherrypy.response.status = 201
+
+        if len(args) != 1:
+            return rest_error(400, 'Invalid arguments. Found %d'
+                                   ' there should be one.')
+        name = args[0]
+        metadata = kwargs.get('metadata')
+
+        obj = self._site[FACILITY].available[self.parent.plugin_name]
+        try:
+            spc = ServiceProviderCreator(obj)
+            sp = spc.create_from_buffer(name, metadata)
+        except (InvalidProviderId, ServerAddProviderFailedError) as e:
+            self._debug(repr(e))
+            return rest_error(400, str(e))
+        except Exception, e:  # pylint: disable=broad-except
+            self._debug(repr(e))
+            return rest_error(500, "Failed to create Service Provider")
+
+        obj.admin.add_sp(name, sp)
+
+        # Added. Now fetch and return the SP data
+        return self._get_sp(name)