Mercurial > public > sg101
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 |