Mercurial > public > sg101
diff user_photos/forms.py @ 701:094492e66eb9
Implement rate limiting on user photo uploads.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 14 Sep 2013 17:23:13 -0500 |
parents | e888d627928f |
children | b6e98717690b |
line wrap: on
line diff
--- a/user_photos/forms.py Wed Sep 11 20:31:23 2013 -0500 +++ b/user_photos/forms.py Sat Sep 14 17:23:13 2013 -0500 @@ -6,9 +6,26 @@ from core.s3 import S3Bucket from core.image_uploader import upload +from core.services import get_redis_connection from user_photos.models import Photo +def rate_limit(key, limit, seconds): + """Use Redis to do a rate limit check. Returns True if the limit is violated + and False otherwise. + + key - the key to check in Redis + limit - the rate limit maximum value + seconds - the rate limit period in seconds + + """ + conn = get_redis_connection() + val = conn.incr(key) + if val == 1: + conn.expire(key, seconds) + return val > limit + + class UploadForm(forms.Form): image_file = forms.ImageField() @@ -16,6 +33,18 @@ self.user = kwargs.pop('user') super(UploadForm, self).__init__(*args, **kwargs) + def clean(self): + cleaned_data = super(UploadForm, self).clean() + + # rate limit uploads + key = 'user_photos:counts:' + self.user.username + limit = settings.USER_PHOTOS_RATE_LIMIT + if rate_limit(key, *limit): + raise forms.ValidationError("You've exceeded your upload quota. " + "Please try again later.") + + return cleaned_data + def save(self): """Processes the image and creates a new Photo object, which is saved to the database. The new Photo instance is returned.