~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/webapp/base/rest.py

  • Committer: Matt Giuca
  • Date: 2009-03-24 06:50:39 UTC
  • mto: This revision was merged to the branch mainline in revision 1322.
  • Revision ID: matt.giuca@gmail.com-20090324065039-5c6xkjeb8x2f5d01
doc/conf.py: Renamed project from "ivle" to "IVLE". (Turns out this is a
    friendly name).

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
# Author: Matt Giuca, Will Grant
19
19
 
20
20
import cgi
 
21
import urlparse
21
22
import inspect
22
23
 
23
24
import cjson
24
25
 
25
26
from ivle.webapp.base.views import BaseView
26
 
from ivle.webapp.errors import BadRequest, MethodNotAllowed
 
27
from ivle.webapp.errors import BadRequest, MethodNotAllowed, Unauthorized
27
28
 
28
29
class RESTView(BaseView):
29
30
    """
49
50
        lambda self: [m for m in ('GET', 'PUT', 'PATCH')
50
51
                      if hasattr(self, m)] + ['POST'])
51
52
 
 
53
    def authorize(self, req):
 
54
        return True # Real authz performed in render().
 
55
 
 
56
    def authorize_method(self, req, op):
 
57
        if not hasattr(op, '_rest_api_permission'):
 
58
            raise Unauthorized()
 
59
 
 
60
        if op._rest_api_permission not in self.get_permissions(req.user):
 
61
            raise Unauthorized()
 
62
    
 
63
    def convert_bool(self, value):
 
64
        if value in ('True', 'true', True):
 
65
            return True
 
66
        elif value in ('False', 'false', False):
 
67
            return False
 
68
        else:
 
69
            raise BadRequest()
 
70
 
52
71
    def render(self, req):
53
72
        if req.method not in self._allowed_methods:
54
73
            raise MethodNotAllowed(allowed=self._allowed_methods)
55
74
 
56
75
        if req.method == 'GET':
 
76
            self.authorize_method(req, self.GET)
57
77
            outjson = self.GET(req)
58
78
        # Since PATCH isn't yet an official HTTP method, we allow users to
59
79
        # turn a PUT into a PATCH by supplying a special header.
60
80
        elif req.method == 'PATCH' or (req.method == 'PUT' and
61
81
              'X-IVLE-Patch-Semantics' in req.headers_in and
62
82
              req.headers_in['X-IVLE-Patch-Semantics'].lower() == 'yes'):
 
83
            self.authorize_method(req, self.PATCH)
63
84
            try:
64
85
                input = cjson.decode(req.read())
65
86
            except cjson.DecodeError:
66
87
                raise BadRequest('Invalid JSON data')
67
88
            outjson = self.PATCH(req, input)
68
89
        elif req.method == 'PUT':
 
90
            self.authorize_method(req, self.PUT)
69
91
            try:
70
92
                input = cjson.decode(req.read())
71
93
            except cjson.DecodeError:
74
96
        # POST implies named operation.
75
97
        elif req.method == 'POST':
76
98
            # TODO: Check Content-Type and implement multipart/form-data.
77
 
            opargs = dict(cgi.parse_qsl(req.read()))
 
99
            data = req.read()
 
100
            opargs = dict(cgi.parse_qsl(data, keep_blank_values=1))
78
101
            try:
79
102
                opname = opargs['ivle.op']
80
103
                del opargs['ivle.op']
90
113
               not op._rest_api_callable:
91
114
                raise BadRequest('Invalid named operation.')
92
115
 
 
116
            self.authorize_method(req, op)
 
117
 
93
118
            # Find any missing arguments, except for the first two (self, req)
94
119
            (args, vaargs, varkw, defaults) = inspect.getargspec(op)
95
120
            args = args[2:]
120
145
            req.write(cjson.encode(outjson))
121
146
            req.write("\n")
122
147
 
123
 
def named_operation(meth):
 
148
class named_operation(object):
124
149
    '''Declare a function to be accessible to HTTP users via the REST API.
125
150
    '''
126
 
    meth._rest_api_callable = True
127
 
    return meth
 
151
    def __init__(self, permission):
 
152
        self.permission = permission
 
153
 
 
154
    def __call__(self, func):
 
155
        func._rest_api_callable = True
 
156
        func._rest_api_permission = self.permission
 
157
        return func
 
158
 
 
159
class require_permission(object):
 
160
    '''Declare the permission required for use of a method via the REST API.
 
161
    '''
 
162
    def __init__(self, permission):
 
163
        self.permission = permission
 
164
 
 
165
    def __call__(self, func):
 
166
        func._rest_api_permission = self.permission
 
167
        return func
128
168