Mercurial > public > sg101
diff antispam/decorators.py @ 581:ee87ea74d46b
For Django 1.4, rearranged project structure for new manage.py.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 05 May 2012 17:10:48 -0500 |
parents | gpp/antispam/decorators.py@a5d11471d031 |
children | 89b240fe9297 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/antispam/decorators.py Sat May 05 17:10:48 2012 -0500 @@ -0,0 +1,59 @@ +""" +This module contains decorators for the antispam application. + +""" +from datetime import timedelta +from functools import wraps + +from django.shortcuts import render +from django.utils import simplejson + +from antispam.rate_limit import RateLimiter, RateLimiterUnavailable + + +def rate_limit(count=10, interval=timedelta(minutes=1), + lockout=timedelta(hours=8)): + + def decorator(fn): + + @wraps(fn) + def wrapped(request, *args, **kwargs): + + ip = request.META.get('REMOTE_ADDR') + try: + rate_limiter = RateLimiter(ip, count, interval, lockout) + if rate_limiter.is_blocked(): + return render(request, 'antispam/blocked.html', status=403) + + except RateLimiterUnavailable: + # just call the function and return the result + return fn(request, *args, **kwargs) + + response = fn(request, *args, **kwargs) + + if request.method == 'POST': + + # Figure out if the view succeeded; if it is a non-ajax view, + # then success means a redirect is about to occur. If it is + # an ajax view, we have to decode the json response. + success = False + if not request.is_ajax(): + success = (response and response.has_header('location') and + response.status_code == 302) + elif response: + json_resp = simplejson.loads(response.content) + success = json_resp['success'] + + if not success: + try: + blocked = rate_limiter.incr() + except RateLimiterUnavailable: + blocked = False + + if blocked: + return render(request, 'antispam/blocked.html', status=403) + + return response + + return wrapped + return decorator