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

« back to all changes in this revision

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

Merge from new-dispatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import cjson
24
24
 
25
25
from ivle.webapp.base.views import BaseView
26
 
from ivle.webapp.errors import BadRequest, MethodNotAllowed
 
26
from ivle.webapp.errors import BadRequest, MethodNotAllowed, Unauthorized
27
27
 
28
28
class RESTView(BaseView):
29
29
    """
49
49
        lambda self: [m for m in ('GET', 'PUT', 'PATCH')
50
50
                      if hasattr(self, m)] + ['POST'])
51
51
 
 
52
    def authorize(self, req):
 
53
        return True # Real authz performed in render().
 
54
 
 
55
    def authorize_method(self, req, op):
 
56
        if not hasattr(op, '_rest_api_permission'):
 
57
            raise Unauthorized()
 
58
 
 
59
        if op._rest_api_permission not in self.get_permissions(req.user):
 
60
            raise Unauthorized()
 
61
 
52
62
    def render(self, req):
53
63
        if req.method not in self._allowed_methods:
54
64
            raise MethodNotAllowed(allowed=self._allowed_methods)
55
65
 
56
66
        if req.method == 'GET':
 
67
            self.authorize_method(req, self.GET)
57
68
            outjson = self.GET(req)
58
69
        # Since PATCH isn't yet an official HTTP method, we allow users to
59
70
        # turn a PUT into a PATCH by supplying a special header.
60
71
        elif req.method == 'PATCH' or (req.method == 'PUT' and
61
72
              'X-IVLE-Patch-Semantics' in req.headers_in and
62
73
              req.headers_in['X-IVLE-Patch-Semantics'].lower() == 'yes'):
 
74
            self.authorize_method(req, self.PATCH)
63
75
            try:
64
76
                input = cjson.decode(req.read())
65
77
            except cjson.DecodeError:
66
78
                raise BadRequest('Invalid JSON data')
67
79
            outjson = self.PATCH(req, input)
68
80
        elif req.method == 'PUT':
 
81
            self.authorize_method(req, self.PUT)
69
82
            try:
70
83
                input = cjson.decode(req.read())
71
84
            except cjson.DecodeError:
90
103
               not op._rest_api_callable:
91
104
                raise BadRequest('Invalid named operation.')
92
105
 
 
106
            self.authorize_method(req, op)
 
107
 
93
108
            # Find any missing arguments, except for the first two (self, req)
94
109
            (args, vaargs, varkw, defaults) = inspect.getargspec(op)
95
110
            args = args[2:]
120
135
            req.write(cjson.encode(outjson))
121
136
            req.write("\n")
122
137
 
123
 
def named_operation(meth):
 
138
class named_operation(object):
124
139
    '''Declare a function to be accessible to HTTP users via the REST API.
125
140
    '''
126
 
    meth._rest_api_callable = True
127
 
    return meth
 
141
    def __init__(self, permission):
 
142
        self.permission = permission
 
143
 
 
144
    def __call__(self, func):
 
145
        func._rest_api_callable = True
 
146
        func._rest_api_permission = self.permission
 
147
        return func
 
148
 
 
149
class require_permission(object):
 
150
    '''Declare the permission required for use of a method via the REST API.
 
151
    '''
 
152
    def __init__(self, permission):
 
153
        self.permission = permission
 
154
 
 
155
    def __call__(self, func):
 
156
        func._rest_api_permission = self.permission
 
157
        return func
128
158