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