view roundup/rest.py @ 5560:2cc07def1b3f REST-rebased

use getattr instead of calling each function committer: Ralf Schlatterbeck <rsc@runtux.com>
author Chau Nguyen <dangchau1991@yahoo.com>
date Wed, 30 Jan 2019 10:26:33 +0100
parents 3d80e7752783
children 7aa7f779198b
line wrap: on
line source

"""
Restful API for Roundup

This module is free software, you may redistribute it
and/or modify under the same terms as Python.
"""

import json
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):
        # TODO: database, translator and instance.actions
        self.db = db

    def action_get(self, resource_uri, input):
        # TODO: split this into collection URI and resource URI
        class_name = resource_uri
        try:
            class_obj = self.db.getclass(class_name)
            """prop_name = class_obj.labelprop()
            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)
                      ]
            result = json.JSONEncoder().encode(result)
            # result = `len(dict(result))` + ' ' + `len(result)`
        except KeyError:
            pass

        try:
            class_name, item_id = hyperdb.splitDesignator(resource_uri)
            class_obj = self.db.getclass(class_name)
            props = class_obj.properties.keys()
            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)
                      ]
            # Note: is this a bug by having an extra indent in xmlrpc ?
            result = json.JSONEncoder().encode(dict(result))
        except hyperdb.DesignatorError:
            pass

        return 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
        #       crash at line self.form = cgi.FieldStorage(fp=request.rfile, environ=env)
        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
        print type(input)
        pprint.pprint(input)

        # PATH is split to multiple pieces
        # 0 - rest
        # 1 - resource
        #
        # 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: 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.
        try:
            output = getattr(self, "action_%s" % method.lower())(uri_path[1], input_form)
        except AttributeError:
            raise NotImplementedError

        print "Response Length: %s - Response Content (First 50 char): %s" %\
              (len(output), output[:50])
        return output

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