15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
# Author: Matt Giuca, Will Grant
18
# Author: Matt Giuca, Will Grant, Nick Chadwick
26
import genshi.template
25
28
from ivle.webapp.base.views import BaseView
29
from ivle.webapp.base.xhtml import GenshiLoaderMixin
26
30
from ivle.webapp.errors import BadRequest, MethodNotAllowed, Unauthorized
28
32
class RESTView(BaseView):
33
37
content_type = "application/octet-stream"
35
def __init__(self, req, *args, **kwargs):
37
setattr(self, key, kwargs[key])
39
39
def render(self, req):
40
40
raise NotImplementedError()
56
56
if not hasattr(op, '_rest_api_permission'):
57
57
raise Unauthorized()
59
if op._rest_api_permission not in self.get_permissions(req.user):
59
if (op._rest_api_permission not in
60
self.get_permissions(req.user, req.config)):
60
61
raise Unauthorized()
63
def convert_bool(self, value):
64
if value in ('True', 'true', True):
66
elif value in ('False', 'false', False):
62
71
def render(self, req):
63
72
if req.method not in self._allowed_methods:
87
96
# POST implies named operation.
88
97
elif req.method == 'POST':
89
98
# TODO: Check Content-Type and implement multipart/form-data.
90
opargs = dict(cgi.parse_qsl(req.read()))
100
opargs = dict(cgi.parse_qsl(data, keep_blank_values=1))
92
102
opname = opargs['ivle.op']
93
103
del opargs['ivle.op']
131
141
outjson = op(req, **opargs)
133
143
req.content_type = self.content_type
144
self.write_json(req, outjson)
146
#This is a separate function to allow additional data to be passed through
147
def write_json(self, req, outjson):
134
148
if outjson is not None:
135
149
req.write(cjson.encode(outjson))
153
class XHTMLRESTView(GenshiLoaderMixin, JSONRESTView):
154
"""A special type of RESTView which takes enhances the standard JSON
155
with genshi XHTML functions.
157
XHTMLRESTViews should have a template, which is rendered using their
158
context. This is returned in the JSON as 'html'"""
160
ctx = genshi.template.Context()
162
def render_fragment(self):
163
if self.template is None:
164
raise NotImplementedError()
166
rest_template = os.path.join(os.path.dirname(
167
inspect.getmodule(self).__file__), self.template)
168
tmpl = self._loader.load(rest_template)
170
return tmpl.generate(self.ctx).render('xhtml', doctype='xhtml')
172
# This renders the template and adds it to the json
173
def write_json(self, req, outjson):
174
outjson["html"] = self.render_fragment()
175
req.write(cjson.encode(outjson))
138
178
class named_operation(object):
139
179
'''Declare a function to be accessible to HTTP users via the REST API.