annotate antispam/decorators.py @ 683:c83d330cb65f

For Django 1.5: LOGIN_* related settings take url names now.
author Brian Neal <bgneal@gmail.com>
date Fri, 23 Aug 2013 19:02:45 -0500
parents 89b240fe9297
children 988782c6ce6c
rev   line source
bgneal@472 1 """
bgneal@472 2 This module contains decorators for the antispam application.
bgneal@472 3
bgneal@472 4 """
bgneal@472 5 from datetime import timedelta
bgneal@679 6 import json
bgneal@472 7 from functools import wraps
bgneal@472 8
bgneal@472 9 from django.shortcuts import render
bgneal@472 10
bgneal@473 11 from antispam.rate_limit import RateLimiter, RateLimiterUnavailable
bgneal@472 12
bgneal@472 13
bgneal@472 14 def rate_limit(count=10, interval=timedelta(minutes=1),
bgneal@472 15 lockout=timedelta(hours=8)):
bgneal@472 16
bgneal@472 17 def decorator(fn):
bgneal@472 18
bgneal@472 19 @wraps(fn)
bgneal@472 20 def wrapped(request, *args, **kwargs):
bgneal@472 21
bgneal@473 22 ip = request.META.get('REMOTE_ADDR')
bgneal@473 23 try:
bgneal@473 24 rate_limiter = RateLimiter(ip, count, interval, lockout)
bgneal@479 25 if rate_limiter.is_blocked():
bgneal@479 26 return render(request, 'antispam/blocked.html', status=403)
bgneal@479 27
bgneal@473 28 except RateLimiterUnavailable:
bgneal@473 29 # just call the function and return the result
bgneal@473 30 return fn(request, *args, **kwargs)
bgneal@473 31
bgneal@472 32 response = fn(request, *args, **kwargs)
bgneal@472 33
bgneal@472 34 if request.method == 'POST':
bgneal@505 35
bgneal@505 36 # Figure out if the view succeeded; if it is a non-ajax view,
bgneal@505 37 # then success means a redirect is about to occur. If it is
bgneal@505 38 # an ajax view, we have to decode the json response.
bgneal@505 39 success = False
bgneal@505 40 if not request.is_ajax():
bgneal@505 41 success = (response and response.has_header('location') and
bgneal@505 42 response.status_code == 302)
bgneal@505 43 elif response:
bgneal@679 44 json_resp = json.loads(response.content)
bgneal@505 45 success = json_resp['success']
bgneal@505 46
bgneal@505 47 if not success:
bgneal@505 48 try:
bgneal@505 49 blocked = rate_limiter.incr()
bgneal@505 50 except RateLimiterUnavailable:
bgneal@505 51 blocked = False
bgneal@505 52
bgneal@505 53 if blocked:
bgneal@479 54 return render(request, 'antispam/blocked.html', status=403)
bgneal@479 55
bgneal@472 56 return response
bgneal@472 57
bgneal@472 58 return wrapped
bgneal@472 59 return decorator