generalize bootleg throttle thing

pull/1/head
nathaniel smith 2016-12-19 23:03:36 -08:00
parent 4acf87733a
commit 04ca1fd058
4 changed files with 36 additions and 23 deletions

View File

@ -1,3 +1,4 @@
from datetime import datetime, timedelta
from random import shuffle from random import shuffle
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -17,9 +18,26 @@ def validate_captcha(captcha):
if captcha != NOT_A_ROBOT: if captcha != NOT_A_ROBOT:
raise ValidationError('Are you sure you are not a robot?') raise ValidationError('Are you sure you are not a robot?')
class CaptchaField(ChoiceField): class CaptchaField(ChoiceField):
def __init__(self): def __init__(self):
super().__init__(choices=CAPTCHA_CHOICES, super().__init__(choices=CAPTCHA_CHOICES,
label='are you a robot?', label='are you a robot?',
help_text='pick the response that indicates whether or not you are a robot.', help_text='pick the response that indicates whether or not you are a robot.',
validators=(validate_captcha,)) validators=(validate_captcha,))
# this should go in something like redis. I refuse, however, to involve redis
# in all of this until i have 2-3 more usecases.
def throttler(cache):
def throttle(key):
nonlocal cache
last_submission = cache.get(key)
now = datetime.now()
if last_submission is None\
or now - last_submission > timedelta(minutes=30):
cache[key] = now
else:
raise ValidationError('you have submitted pretty recently. try again in a bit.')
return throttle

View File

@ -0,0 +1,14 @@
from datetime import datetime, timedelta
from django.core.exceptions import ValidationError
def throttler(cache):
def throttle(key):
nonlocal cache
last_submission = cache.get(key)
if last_submission is None\
or now - last_submission > timedelta(minutes=30):
cache[key] = now
else:
raise ValidationError('you have submitted pretty recently. try again in a bit.')
return throttle

View File

@ -3,22 +3,12 @@ from datetime import datetime, timedelta
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import Form, CharField, EmailField, Textarea, ChoiceField from django.forms import Form, CharField, EmailField, Textarea, ChoiceField
from common.forms import CaptchaField from common.forms import CaptchaField, throttler
# this should go in something like redis. I refuse, however, to involve redis
# in all of this until i have 2-3 more usecases.
# TODO generalize
submission_throttle = {} submission_throttle = {}
throttle_submission = throttler(submission_throttle)
def throttle_submission(name):
last_submission = submission_throttle.get(name)
now = datetime.now()
if last_submission is None\
or now - last_submission > timedelta(minutes=30):
submission_throttle[name] = datetime.now()
else:
raise ValidationError('you have submitted pretty recently. try again in a bit.')
def validate_msg_text(msg): def validate_msg_text(msg):
if len(msg) == 0: if len(msg) == 0:

View File

@ -3,22 +3,13 @@ from datetime import datetime, timedelta
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import Form, CharField, EmailField, Textarea, ChoiceField from django.forms import Form, CharField, EmailField, Textarea, ChoiceField
from common.forms import CaptchaField from common.forms import CaptchaField, throttler
from .models import ISSUE_TYPE_CHOICES from .models import ISSUE_TYPE_CHOICES
# this should go in something like redis. I refuse, however, to involve redis
# in all of this until i have 2-3 more usecases.
submission_throttle = {} submission_throttle = {}
throttle_submission = throttler(submission_throttle)
def throttle_submission(email):
last_submission = submission_throttle.get(email)
now = datetime.now()
if last_submission is None\
or now - last_submission > timedelta(minutes=30):
submission_throttle[email] = datetime.now()
else:
raise ValidationError('you have submitted pretty recently. try again in a bit.')
def validate_issue_text(text): def validate_issue_text(text):
if len(text) == 0: if len(text) == 0: