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

« back to all changes in this revision

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

ivle.webapp.groups: Remove most of the view code; the template now accesses
    the objects directly. Also fix a few double-encodings and typos.

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