view antispam/decorators.py @ 645:99f7917702ca

Fix 081a88b3bfc8, javascript resize of forum images. Commit 081a88b3bfc8 broke those pages that loaded forums.js but did not load the imagesLoaded jQuery extension. Now we have arranged it so that only the forums topic view loads imagesLoaded and put the resizing javascript inline.
author Brian Neal <bgneal@gmail.com>
date Mon, 11 Mar 2013 15:30:25 -0500
parents ee87ea74d46b
children 89b240fe9297
line wrap: on
line source
"""
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