comparison user_photos/forms.py @ 971:4f265f61874b

Hotlink image form is functioning. The user can now submit a URL via a form and the URL will be downloaded and uploaded to a S3 bucket if it is an image. Tests to follow.
author Brian Neal <bgneal@gmail.com>
date Tue, 22 Sep 2015 20:23:50 -0500
parents 51a2051588f5
children 7138883966b3
comparison
equal deleted inserted replaced
970:bd594bcba5eb 971:4f265f61874b
1 """Forms for the user_photos application.""" 1 """Forms for the user_photos application."""
2 import datetime 2 import datetime
3 import hashlib 3 import hashlib
4 import os.path 4 import os.path
5 import urlparse
5 6
6 from django import forms 7 from django import forms
7 from django.conf import settings 8 from django.conf import settings
8 9
10 from core.download import download_file
11 from core.functions import TemporaryFile
12 from core.images.upload import upload
9 from core.s3 import S3Bucket 13 from core.s3 import S3Bucket
10 from core.image_uploader import upload
11 from core.functions import TemporaryFile
12 from core.services import get_redis_connection 14 from core.services import get_redis_connection
13 from user_photos.models import Photo 15 from user_photos.models import Photo
14 16
15 17
16 def rate_limit(key, limit, seconds): 18 def rate_limit(key, limit, seconds):
27 if val == 1: 29 if val == 1:
28 conn.expire(key, seconds) 30 conn.expire(key, seconds)
29 return val > limit 31 return val > limit
30 32
31 33
34 def rate_limit_user(user):
35 """Shared function to rate limit user uploads."""
36 key = 'user_photos:counts:' + user.username
37 limit = settings.USER_PHOTOS_RATE_LIMIT
38 if rate_limit(key, *limit):
39 raise forms.ValidationError("You've exceeded your upload quota. "
40 "Please try again later.")
41
42
32 class UploadForm(forms.Form): 43 class UploadForm(forms.Form):
33 image_file = forms.ImageField() 44 image_file = forms.ImageField()
34 45
35 def __init__(self, *args, **kwargs): 46 def __init__(self, *args, **kwargs):
36 self.user = kwargs.pop('user') 47 self.user = kwargs.pop('user')
37 super(UploadForm, self).__init__(*args, **kwargs) 48 super(UploadForm, self).__init__(*args, **kwargs)
38 49
39 def clean(self): 50 def clean(self):
40 cleaned_data = super(UploadForm, self).clean() 51 cleaned_data = super(UploadForm, self).clean()
41 52 rate_limit_user(self.user)
42 # rate limit uploads
43 key = 'user_photos:counts:' + self.user.username
44 limit = settings.USER_PHOTOS_RATE_LIMIT
45 if rate_limit(key, *limit):
46 raise forms.ValidationError("You've exceeded your upload quota. "
47 "Please try again later.")
48
49 return cleaned_data 53 return cleaned_data
50 54
51 def save(self): 55 def save(self):
52 """Processes the image and creates a new Photo object, which is saved to 56 """Processes the image and creates a new Photo object, which is saved to
53 the database. The new Photo instance is returned. 57 the database. The new Photo instance is returned.
111 fp = self.cleaned_data['image_file'] 115 fp = self.cleaned_data['image_file']
112 md5 = hashlib.md5() 116 md5 = hashlib.md5()
113 for chunk in fp.chunks(): 117 for chunk in fp.chunks():
114 md5.update(chunk) 118 md5.update(chunk)
115 return md5.hexdigest() 119 return md5.hexdigest()
120
121
122 class HotLinkImageForm(forms.Form):
123 """Form for hot-linking images. If the supplied URL's host is on
124 a white-list, return it as-is. Otherwise attempt to download the image at
125 the given URL and upload it into our S3 storage. The URL to the new location
126 is returned.
127 """
128 url = forms.URLField()
129
130 def __init__(self, *args, **kwargs):
131 self.user = kwargs.pop('user')
132 super(HotLinkImageForm, self).__init__(*args, **kwargs)
133
134 def clean_url(self):
135 the_url = self.cleaned_data['url']
136 self.url_parts = urlparse.urlsplit(the_url)
137 if self.url_parts.scheme not in ['http', 'https']:
138 raise forms.ValidationError("Invalid URL scheme")
139 return the_url
140
141 def clean(self):
142 cleaned_data = super(HotLinkImageForm, self).clean()
143 rate_limit_user(self.user)
144 return cleaned_data
145
146 def save(self):
147 import pdb; pdb.set_trace()
148
149 url = self.url_parts.geturl()
150 if (self.url_parts.scheme == 'https' and
151 self.url_parts.hostname in settings.USER_IMAGES_SOURCES):
152 return url
153
154 # Try to download the file
155 path = download_file(url)
156
157 # Upload it to our S3 bucket
158 bucket = S3Bucket(access_key=settings.USER_PHOTOS_ACCESS_KEY,
159 secret_key=settings.USER_PHOTOS_SECRET_KEY,
160 base_url=settings.HOT_LINK_PHOTOS_BASE_URL,
161 bucket_name=settings.HOT_LINK_PHOTOS_BUCKET)
162
163 now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
164 metadata = {'user': self.user.username, 'date': now}
165
166 url, _ = upload(filename=path,
167 bucket=bucket,
168 metadata=metadata,
169 new_size=settings.USER_PHOTOS_MAX_SIZE)
170
171 return url