You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
isso/isso/views/comment.py

134 lines
3.9 KiB

# -*- encoding: utf-8 -*-
#
# Copyright 2012, Martin Zimmermann <info@posativ.org>. All rights reserved.
# License: BSD Style, 2 clauses. see isso/__init__.py
import cgi
import urllib
12 years ago
from itsdangerous import SignatureExpired, BadSignature
from werkzeug.wrappers import Response
from werkzeug.exceptions import abort, BadRequest
from isso import models, utils
class requires:
def __init__(self, type, param):
self.param = param
self.type = type
def __call__(self, func):
def dec(app, env, req, *args, **kwargs):
if self.param not in req.args:
raise BadRequest("missing %s query" % self.param)
try:
kwargs[self.param] = self.type(req.args[self.param])
except TypeError:
raise BadRequest("invalid type for %s, expected %s" % (self.param, self.type))
return func(app, env, req, *args, **kwargs)
return dec
@requires(str, 'uri')
def create(app, environ, request, uri):
if app.PRODUCTION and not utils.urlexists(app.HOST, uri):
return Response('URI does not exist', 400)
try:
comment = models.Comment.fromjson(request.data, ip=request.remote_addr)
12 years ago
except ValueError as e:
return Response(unicode(e), 400)
for attr in 'author', 'website':
if getattr(comment, attr) is not None:
try:
setattr(comment, attr, cgi.escape(getattr(comment, attr)))
except AttributeError:
Response('', 400)
try:
rv = app.db.add(uri, comment)
except ValueError:
abort(400) # FIXME: custom exception class, error descr
md5 = rv.md5
rv.text = app.markdown(rv.text)
resp = Response(app.dumps(rv), 202 if rv.pending else 201,
content_type='application/json')
resp.set_cookie('%s-%s' % (uri, rv.id), app.sign([uri, rv.id, md5]),
max_age=app.MAX_AGE, path='/')
return resp
@requires(str, 'uri')
def get(app, environ, request, uri):
id = request.args.get('id', None)
rv = list(app.db.retrieve(uri)) if id is None else app.db.get(uri, id)
if not rv:
abort(404)
if request.args.get('plain', '1') == '0':
if isinstance(rv, list):
for item in rv:
item.text = app.markdown(item.text)
else:
rv.text = app.markdown(rv.text)
return Response(app.dumps(rv), 200, content_type='application/json')
@requires(str, 'uri')
@requires(int, 'id')
def modify(app, environ, request, uri, id):
12 years ago
try:
rv = app.unsign(request.cookies.get('%s-%s' % (uri, id), ''))
12 years ago
except (SignatureExpired, BadSignature) as e:
try:
12 years ago
rv = app.unsign(request.cookies.get('admin', ''))
except (SignatureExpired, BadSignature):
abort(403)
12 years ago
# verify checksum, mallory might skip cookie deletion when he deletes a comment
if not (rv == '*' or rv[0:2] == [uri, id] or app.db.get(uri, id).md5 != rv[2]):
abort(403)
12 years ago
if request.method == 'PUT':
try:
rv = app.db.update(uri, id, models.Comment.fromjson(request.data))
rv.text = app.markdown(rv.text)
return Response(app.dumps(rv), 200, content_type='application/json')
except ValueError as e:
return Response(unicode(e), 400) # FIXME: custom exception and error descr
if request.method == 'DELETE':
rv = app.db.delete(uri, id)
resp = Response(app.dumps(rv), 200, content_type='application/json')
resp.delete_cookie(uri + '-' + str(id), path='/')
return resp
12 years ago
def approve(app, environ, request, path, id):
try:
12 years ago
if app.unsign(request.cookies.get('admin', '')) != '*':
abort(403)
12 years ago
except (SignatureExpired, BadSignature):
abort(403)
12 years ago
app.db.activate(path, id)
return Response(app.dumps(app.db.get(path, id)), 200,
content_type='application/json')