diff roundup/rest.py @ 5559:3d80e7752783 REST-rebased

Added POST and DELETE [[Ralf Schlatterbeck: Add *all* http methods in roundup_server.py as done on the bugs.python.org branch]] committer: Ralf Schlatterbeck <rsc@runtux.com>
author Chau Nguyen <dangchau1991@yahoo.com>
date Wed, 30 Jan 2019 10:25:12 +0100
parents 1bef1076ad12
children 2cc07def1b3f
line wrap: on
line diff
--- a/roundup/rest.py	Tue Jan 29 15:27:37 2019 +0100
+++ b/roundup/rest.py	Wed Jan 30 10:25:12 2019 +0100
@@ -9,10 +9,12 @@
 import pprint
 from roundup import hyperdb
 from roundup.cgi.templating import Unauthorised
+from roundup import xmlrpc
 
 
 class RestfulInstance(object):
     """Dummy Handler for REST
+       WARNING: Very ugly !!!!, cleaned & better organized in progress (next commit)
     """
 
     def __init__(self, db):
@@ -25,19 +27,17 @@
         try:
             class_obj = self.db.getclass(class_name)
             """prop_name = class_obj.labelprop()
-            result = [class_obj.get(item_id, prop_name)
-                      for item_id in class_obj.list()
-                      if self.db.security.hasPermission('View', self.db.getuid(),
-                                                        class_name, prop_name, item_id)
-                      ]
-            result = json.JSONEncoder().encode(result)"""
+            result = [class_obj.get(item_id, prop_name)"""
             result = [{'id': item_id}
                       for item_id in class_obj.list()
-                      if self.db.security.hasPermission('View', self.db.getuid(),
-                                                        class_name, None, item_id)
+                      if self.db.security.hasPermission('View',
+                                                        self.db.getuid(),
+                                                        class_name,
+                                                        None,
+                                                        item_id)
                       ]
             result = json.JSONEncoder().encode(result)
-            #result = `len(dict(result))` + ' ' + `len(result)`
+            # result = `len(dict(result))` + ' ' + `len(result)`
         except KeyError:
             pass
 
@@ -48,19 +48,78 @@
             props.sort()
             result = [(prop_name, class_obj.get(item_id, prop_name))
                       for prop_name in props
-                      if self.db.security.hasPermission('View', self.db.getuid(),
-                                                        class_name, prop_name, item_id)
+                      if self.db.security.hasPermission('View',
+                                                        self.db.getuid(),
+                                                        class_name,
+                                                        prop_name,
+                                                        item_id)
                       ]
             # Note: is this a bug by having an extra indent in xmlrpc ?
             result = json.JSONEncoder().encode(dict(result))
         except hyperdb.DesignatorError:
             pass
 
-        # print type(result)
-        # print type(dict(result))
         return result
-        # return json.dumps(dict(result))
-        # return dict(result)
+
+    def action_post(self, resource_uri, input):
+        class_name = resource_uri
+
+        if not self.db.security.hasPermission('Create', self.db.getuid(),
+                                              class_name):
+            raise Unauthorised('Permission to create %s denied' % class_name)
+
+        class_obj = self.db.getclass(class_name)
+
+        # convert types
+        props = xmlrpc.props_from_args(self.db, class_obj, input)
+
+        # check for the key property
+        key = class_obj.getkey()
+        if key and key not in props:
+            raise xmlrpc.UsageError, 'Must provide the "%s" property.' % key
+
+        for key in props:
+            if not self.db.security.hasPermission('Create', self.db.getuid(),
+                                                  class_name, property=key):
+                raise Unauthorised('Permission to create %s.%s denied' %
+                                   (class_name, key))
+
+        # do the actual create
+        try:
+            result = class_obj.create(**props)
+            self.db.commit()
+        except (TypeError, IndexError, ValueError), message:
+            raise xmlrpc.UsageError, message
+        return result
+
+    def action_put(self, resource_uri, input):
+        raise NotImplementedError
+
+    def action_delete(self, resource_uri, input):
+        # TODO: should I allow user to delete the whole collection ?
+        # TODO: BUG with DELETE without form data. Working with random data
+        class_name = resource_uri
+        try:
+            class_obj = self.db.getclass(class_name)
+            raise NotImplementedError
+        except KeyError:
+            pass
+
+        try:
+            class_name, item_id = hyperdb.splitDesignator(resource_uri)
+            print class_name
+            print item_id
+            self.db.destroynode(class_name, item_id)
+            result = 'OK'
+        except IndexError:
+            result = 'Error'
+        except hyperdb.DesignatorError:
+            pass
+
+        return result
+
+    def action_patch(self, resource_uri, input):
+        raise NotImplementedError
 
     def dispatch(self, method, uri, input):
         print "METHOD: " + method + " URI: " + uri
@@ -74,22 +133,28 @@
         # Example: rest/issue - collection uri
         # Example: rest/issue573 - element uri
         uri_path = uri.split("/")
+        input_form = ["%s=%s" % (item.name, item.value) for item in input]
+        # TODO: process input_form directly instead of making a new array
+        # TODO: rest server
         # TODO: use named function for this instead
         # TODO: check roundup/actions.py
         # TODO: if uri_path has more than 2 child, return 404
+        # TODO: custom JSONEncoder to handle other data type
+        # TODO: catch all error and display error.
         output = "METHOD is not supported"
         if method == "GET":
-            output = self.action_get(uri_path[1], input)
+            output = self.action_get(uri_path[1], input_form)
         elif method == "POST":
-            pass
+            output = self.action_post(uri_path[1], input_form)
         elif method == "PUT":
-            pass
+            output = self.action_put(uri_path[1], input_form)
         elif method == "DELETE":
-            pass
+            output = self.action_delete(uri_path[1], input_form)
         elif method == "PATCH":
-            pass
+            output = self.action_patch(uri_path[1], input_form)
         else:
             pass
 
-        print "Response Length: " + `len(output)` + " - Response Content (First 50 char): " + output[:50]
+        print "Response Length: %s - Response Content (First 50 char): %s" %\
+              (len(output), output[:50])
         return output

Roundup Issue Tracker: http://roundup-tracker.org/