comparison antispam/decorators.py @ 690:988782c6ce6c

For #48, rework blocking code to use fail2ban.
author Brian Neal <bgneal@gmail.com>
date Sun, 01 Sep 2013 00:15:42 -0500
parents 89b240fe9297
children 4a49d4ac319f
comparison
equal deleted inserted replaced
689:a8dc08cc5db4 690:988782c6ce6c
1 """ 1 """
2 This module contains decorators for the antispam application. 2 This module contains decorators for the antispam application.
3 3
4 """ 4 """
5 from datetime import timedelta
6 import json 5 import json
7 from functools import wraps 6 from functools import wraps
8 7 import logging
9 from django.shortcuts import render
10
11 from antispam.rate_limit import RateLimiter, RateLimiterUnavailable
12 8
13 9
14 def rate_limit(count=10, interval=timedelta(minutes=1), 10 def log_auth_failures(auth_type):
15 lockout=timedelta(hours=8)):
16 11
17 def decorator(fn): 12 def decorator(fn):
13 logger = logging.getLogger('auth')
18 14
19 @wraps(fn) 15 @wraps(fn)
20 def wrapped(request, *args, **kwargs): 16 def wrapped(request, *args, **kwargs):
21
22 ip = request.META.get('REMOTE_ADDR')
23 try:
24 rate_limiter = RateLimiter(ip, count, interval, lockout)
25 if rate_limiter.is_blocked():
26 return render(request, 'antispam/blocked.html', status=403)
27
28 except RateLimiterUnavailable:
29 # just call the function and return the result
30 return fn(request, *args, **kwargs)
31 17
32 response = fn(request, *args, **kwargs) 18 response = fn(request, *args, **kwargs)
33 19
34 if request.method == 'POST': 20 if request.method == 'POST':
35 21
43 elif response: 29 elif response:
44 json_resp = json.loads(response.content) 30 json_resp = json.loads(response.content)
45 success = json_resp['success'] 31 success = json_resp['success']
46 32
47 if not success: 33 if not success:
48 try: 34 username = request.POST.get('username')
49 blocked = rate_limiter.incr() 35 username = username if username else '(None)'
50 except RateLimiterUnavailable: 36 logger.error("%s failure from [%s] for %s",
51 blocked = False 37 auth_type,
52 38 request.META.get('REMOTE_ADDR', '?'),
53 if blocked: 39 username)
54 return render(request, 'antispam/blocked.html', status=403)
55 40
56 return response 41 return response
57 42
58 return wrapped 43 return wrapped
59 return decorator 44 return decorator