annotate gpp/antispam/decorators.py @ 479:32cec6cd8808
Refactor RateLimiter so that if Redis is not running, everything still runs normally (minus the rate limiting protection). My assumption that creating a Redis connection would throw an exception if Redis wasn't running was wrong. The exceptions actually occur when you issue a command. This is for #224.
author |
Brian Neal <bgneal@gmail.com> |
date |
Sun, 25 Sep 2011 00:49:05 +0000 |
parents |
5e826e232932 |
children |
a5d11471d031 |
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@472
|
6 from functools import wraps
|
bgneal@472
|
7
|
bgneal@472
|
8 from django.shortcuts import render
|
bgneal@472
|
9
|
bgneal@473
|
10 from antispam.rate_limit import RateLimiter, RateLimiterUnavailable
|
bgneal@472
|
11
|
bgneal@472
|
12
|
bgneal@472
|
13 def rate_limit(count=10, interval=timedelta(minutes=1),
|
bgneal@472
|
14 lockout=timedelta(hours=8)):
|
bgneal@472
|
15
|
bgneal@472
|
16 def decorator(fn):
|
bgneal@472
|
17
|
bgneal@472
|
18 @wraps(fn)
|
bgneal@472
|
19 def wrapped(request, *args, **kwargs):
|
bgneal@472
|
20
|
bgneal@473
|
21 ip = request.META.get('REMOTE_ADDR')
|
bgneal@473
|
22 try:
|
bgneal@473
|
23 rate_limiter = RateLimiter(ip, count, interval, lockout)
|
bgneal@479
|
24 if rate_limiter.is_blocked():
|
bgneal@479
|
25 return render(request, 'antispam/blocked.html', status=403)
|
bgneal@479
|
26
|
bgneal@473
|
27 except RateLimiterUnavailable:
|
bgneal@473
|
28 # just call the function and return the result
|
bgneal@473
|
29 return fn(request, *args, **kwargs)
|
bgneal@473
|
30
|
bgneal@472
|
31 response = fn(request, *args, **kwargs)
|
bgneal@472
|
32
|
bgneal@472
|
33 if request.method == 'POST':
|
bgneal@472
|
34 success = (response and response.has_header('location') and
|
bgneal@472
|
35 response.status_code == 302)
|
bgneal@479
|
36 try:
|
bgneal@479
|
37 if not success and rate_limiter.incr():
|
bgneal@479
|
38 return render(request, 'antispam/blocked.html', status=403)
|
bgneal@479
|
39
|
bgneal@479
|
40 except RateLimiterUnavailable:
|
bgneal@479
|
41 pass
|
bgneal@472
|
42
|
bgneal@472
|
43 return response
|
bgneal@472
|
44
|
bgneal@472
|
45 return wrapped
|
bgneal@472
|
46 return decorator
|