1. Rufus Pollock
  2. wdmmg


wdmmg / wdmmg / controllers / rest.py

import logging
from datetime import datetime
# http://micheles.googlecode.com/hg/decorator/documentation.html
import decorator
# Docs as per
# http://docs.python.org/release/2.6.5/library/json.html#module-json
import simplejson

from pylons import request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect

from wdmmg.lib.base import BaseController, render
from wdmmg import model

log = logging.getLogger(__name__)

# List of actions that can be performed on a domain object.

# :TODO: Consider moving to lib/ ?
def jsonpify(func, *args, **kwargs):
    """A decorator that reformats the output as JSON; or, if the
    *callback* parameter is specified (in the HTTP request), as JSONP.
    Very much modelled after pylons.decorators.jsonify .

    from pylons.decorators.util import get_pylons

    pylons = get_pylons(args)
    data = func(*args, **kwargs)
    if isinstance(data, (list, tuple)):
        msg = "JSON responses with Array envelopes are susceptible to " \
              "cross-site data leak attacks, see " \
        warnings.warn(msg, Warning, 2)
    result = simplejson.dumps(data)
    if 'callback' in pylons.request.params:
        pylons.response.headers['Content-Type'] = 'text/javascript'
        log.debug("Returning JSONP wrapped action output")
        # The parameter is a unicode object, which we don't want (as it
        # causes Pylons to complain when we return a unicode object from
        # this function).  All reasonable values of this parameter will
        # "str" with no problem (ASCII clean).  So we do that then.
        cbname = str(pylons.request.params['callback'])
        result = '%s(%s);' % (cbname, result)
        pylons.response.headers['Content-Type'] = 'application/json'
        log.debug("Returning JSON wrapped action output")
    return result
jsonpify = decorator.decorator(jsonpify)

class RestController(BaseController):

    def index(self):
        dataset_ = model.Dataset.find_one()
        c.urls = [
            url(controller='rest', action='dataset', name_or_id=dataset_.name),
            url(controller='rest', action='dataset', name_or_id=dataset_.id),
            #url(controller='rest', action='entry', name_or_id=model.Entry.find_one().name),
            url(controller='rest', action='entry', name_or_id=model.Entry.find_one().id),
        return render('home/rest.html')
    def dataset(self, name_or_id=None):
        return self._domain_object(model.Dataset.by_name_or_id(name_or_id))
    def entry(self, name_or_id=None):
        return self._domain_object(model.Entry.by_name_or_id(name_or_id))
    def _domain_object(self, domain_object):
        self._check_access(domain_object, READ)
        return domain_object.to_safe_dict()

    def _check_access(self, domain_object, action):
        Checks whether the supplied `apikey` permits `action` to be performed
        on `domain_object`. If allowed, returns `True`. If forbidden, throws
        an appropriate HTTPException.
        if action == READ:
            return True