snipt/snipts/api.py

488 lines
16 KiB
Python
Raw Normal View History

2015-07-24 18:28:31 -07:00
import datetime
import hashlib
2015-07-24 18:39:25 -07:00
import parsedatetime as pdt
2015-07-24 18:28:31 -07:00
import re
import time
2012-05-27 11:51:21 -07:00
2015-07-24 18:39:25 -07:00
from accounts.models import UserProfile
from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import date, urlize, linebreaksbr
from haystack.query import SearchQuerySet
from snipts.models import Favorite, Snipt
from taggit.models import Tag
from taggit.utils import edit_string_for_tags, parse_tags
from tastypie import fields
from tastypie.authentication import ApiKeyAuthentication
from tastypie.authorization import Authorization
from tastypie.cache import SimpleCache
from tastypie.exceptions import Unauthorized
from tastypie.fields import ListField
from tastypie.models import create_api_key
from tastypie.resources import ModelResource
from tastypie.validation import Validation
2012-04-13 10:13:19 -07:00
2012-01-29 17:48:17 -08:00
models.signals.post_save.connect(create_api_key, sender=User)
2011-10-01 10:23:05 -07:00
2011-10-02 15:38:20 -07:00
class PrivateFavoriteAuthorization(Authorization):
def read_list(self, object_list, bundle):
return object_list.filter(user=bundle.request.user)
def read_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def create_list(self, object_list, bundle):
raise Unauthorized()
def create_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def update_list(self, object_list, bundle):
raise Unauthorized()
def update_detail(self, object_list, bundle):
raise Unauthorized()
def delete_list(self, object_list, bundle):
raise Unauthorized()
def delete_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
2015-07-24 18:28:31 -07:00
class PrivateSniptAuthorization(Authorization):
def read_list(self, object_list, bundle):
return object_list.filter(user=bundle.request.user)
def read_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def create_list(self, object_list, bundle):
raise Unauthorized()
def create_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def update_list(self, object_list, bundle):
raise Unauthorized()
def update_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def delete_list(self, object_list, bundle):
raise Unauthorized()
def delete_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
2015-07-24 18:28:31 -07:00
class PrivateUserProfileAuthorization(Authorization):
def read_list(self, object_list, bundle):
raise Unauthorized()
def read_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def create_list(self, object_list, bundle):
raise Unauthorized()
def create_detail(self, object_list, bundle):
raise Unauthorized()
def update_list(self, object_list, bundle):
raise Unauthorized()
def update_detail(self, object_list, bundle):
return bundle.obj.user == bundle.request.user
def delete_list(self, object_list, bundle):
raise Unauthorized()
def delete_detail(self, object_list, bundle):
raise Unauthorized()
2015-07-24 18:28:31 -07:00
class PrivateUserAuthorization(Authorization):
def read_list(self, object_list, bundle):
raise Unauthorized()
def read_detail(self, object_list, bundle):
return bundle.obj == bundle.request.user
def create_list(self, object_list, bundle):
raise Unauthorized()
def create_detail(self, object_list, bundle):
raise Unauthorized()
def update_list(self, object_list, bundle):
raise Unauthorized()
def update_detail(self, object_list, bundle):
raise Unauthorized()
def delete_list(self, object_list, bundle):
raise Unauthorized()
def delete_detail(self, object_list, bundle):
raise Unauthorized()
2012-04-12 19:04:37 -07:00
class FavoriteValidation(Validation):
def is_valid(self, bundle, request=None):
2012-04-12 19:04:37 -07:00
errors = {}
snipt = bundle.data['snipt']
2015-07-24 18:28:31 -07:00
if Favorite.objects.filter(user=bundle.request.user,
snipt=snipt).count():
2012-04-12 19:04:37 -07:00
errors['duplicate'] = 'User has already favorited this snipt.'
return errors
2015-07-24 18:28:31 -07:00
2014-05-04 19:47:15 -07:00
class SniptValidation(Validation):
def is_valid(self, bundle, request=None):
errors = {}
2015-08-31 07:51:52 -07:00
if request.user.profile.is_pro is False:
if ('public' not in bundle.data or bundle.data['public'] is False):
2015-08-25 09:01:48 -07:00
errors['not-pro'] = ("You'll need to go Pro "
"(https://snipt.net/pro/) "
"in order to create private "
"snipts.")
2014-05-04 19:47:15 -07:00
return errors
2015-07-24 18:28:31 -07:00
class UserProfileValidation(Validation):
def is_valid(self, bundle, request=None):
errors = {}
for field in bundle.data:
if bundle.data[field]:
if not re.match('^[ A-Za-z0-9\/\@\._-]*$', bundle.data[field]):
2015-08-25 09:01:48 -07:00
errors[field] = ("Only spaces, letters, numbers, "
"underscores, dashes, periods, forward "
"slashes, and \"at sign\" are valid.")
return errors
2012-04-12 19:04:37 -07:00
2011-10-01 16:09:59 -07:00
class PublicUserResource(ModelResource):
class Meta:
2011-10-02 13:07:47 -07:00
queryset = User.objects.all()
2011-10-01 16:09:59 -07:00
resource_name = 'user'
2015-07-24 18:28:31 -07:00
fields = ['id', 'username']
2011-10-02 13:16:58 -07:00
include_absolute_url = True
2011-10-03 17:42:00 -07:00
allowed_methods = ['get']
2015-07-24 18:28:31 -07:00
filtering = {'username': 'exact'}
2012-08-27 09:01:37 -07:00
max_limit = 200
2011-10-02 15:57:41 -07:00
cache = SimpleCache()
2011-10-01 16:09:59 -07:00
2011-10-03 17:42:00 -07:00
def dehydrate(self, bundle):
bundle.data['snipts'] = '/api/public/snipt/?user=%d' % bundle.obj.id
2015-07-24 18:28:31 -07:00
bundle.data['email_md5'] = hashlib \
.md5(bundle.obj.email.lower()) \
.hexdigest()
bundle.data['snipts_count'] = Snipt.objects.filter(user=bundle.obj.id,
public=True).count()
2011-10-03 17:42:00 -07:00
return bundle
2011-10-01 16:09:59 -07:00
2015-07-24 18:28:31 -07:00
2014-05-26 14:28:13 -07:00
class PublicTagResource(ModelResource):
class Meta:
queryset = Tag.objects.filter()
2015-07-24 18:28:31 -07:00
queryset = queryset.annotate(
count=models.Count('taggit_taggeditem_items__id'))
2014-05-26 14:28:13 -07:00
queryset = queryset.order_by('-count', 'name')
resource_name = 'tag'
2015-07-24 18:28:31 -07:00
fields = ['id', 'name']
2014-05-26 14:28:13 -07:00
allowed_methods = ['get']
max_limit = 200
cache = SimpleCache()
2014-05-26 14:28:13 -07:00
def build_filters(self, filters=None):
if filters is None:
filters = {}
2014-05-26 14:28:13 -07:00
orm_filters = super(PublicTagResource, self).build_filters(filters)
2014-05-26 14:28:13 -07:00
if 'q' in filters:
orm_filters['slug'] = filters['q']
2014-05-26 14:28:13 -07:00
return orm_filters
2014-05-26 14:28:13 -07:00
def dehydrate(self, bundle):
bundle.data['absolute_url'] = '/public/tag/%s/' % bundle.obj.slug
bundle.data['snipts'] = '/api/public/snipt/?tag=%d' % bundle.obj.id
return bundle
2011-10-01 16:09:59 -07:00
2015-07-24 18:28:31 -07:00
2011-10-01 16:09:59 -07:00
class PublicSniptResource(ModelResource):
2011-10-03 17:42:00 -07:00
user = fields.ForeignKey(PublicUserResource, 'user', full=True)
2015-07-24 18:28:31 -07:00
tags = fields.ToManyField(PublicTagResource, 'tags', related_name='tag',
full=True)
2011-10-01 10:23:05 -07:00
class Meta:
2011-10-02 13:07:47 -07:00
queryset = Snipt.objects.filter(public=True).order_by('-created')
2011-10-01 10:23:05 -07:00
resource_name = 'snipt'
2015-07-24 18:28:31 -07:00
fields = ['id', 'title', 'slug', 'lexer', 'code', 'description',
'line_count', 'stylized', 'created', 'modified',
'publish_date', 'blog_post', 'meta']
2011-10-02 13:16:58 -07:00
include_absolute_url = True
2011-10-03 17:42:00 -07:00
allowed_methods = ['get']
2015-07-24 18:28:31 -07:00
filtering = {'user': 'exact', 'blog_post': 'exact'}
ordering = ['created', 'modified']
2015-09-15 08:57:57 -07:00
max_limit = 200
2011-10-02 15:57:41 -07:00
cache = SimpleCache()
2011-10-01 16:09:59 -07:00
def dehydrate(self, bundle):
2011-10-03 17:42:00 -07:00
bundle.data['embed_url'] = bundle.obj.get_embed_url()
2013-03-15 11:19:28 -07:00
bundle.data['raw_url'] = bundle.obj.get_raw_url()
bundle.data['full_absolute_url'] = bundle.obj.get_full_absolute_url()
2015-07-24 18:28:31 -07:00
bundle.data['description_rendered'] = \
linebreaksbr(urlize(bundle.obj.description))
if 'omit_code' in bundle.request.GET:
del bundle.data['code']
2015-04-03 09:27:02 -07:00
if 'omit_stylized' in bundle.request.GET:
del bundle.data['stylized']
2011-10-01 16:09:59 -07:00
return bundle
2011-10-02 15:38:20 -07:00
def build_filters(self, filters=None):
if filters is None:
filters = {}
orm_filters = super(PublicSniptResource, self).build_filters(filters)
if 'tag' in filters:
tag = Tag.objects.get(pk=filters['tag'])
tagged_items = tag.taggit_taggeditem_items.all()
orm_filters['pk__in'] = [i.object_id for i in tagged_items]
2012-05-09 14:18:09 -07:00
if 'q' in filters:
sqs = SearchQuerySet().auto_query(filters['q'])
orm_filters['pk__in'] = [i.pk for i in sqs]
2011-10-02 15:38:20 -07:00
return orm_filters
2011-12-22 20:36:06 -08:00
class PrivateUserProfileResource(ModelResource):
class Meta:
queryset = UserProfile.objects.all()
resource_name = 'profile'
2013-10-19 17:48:00 -07:00
excludes = ['is_pro']
validation = UserProfileValidation()
include_absolute_url = False
allowed_methods = ['get', 'put']
list_allowed_methods = []
authentication = ApiKeyAuthentication()
authorization = PrivateUserProfileAuthorization()
always_return_data = True
max_limit = 200
def dehydrate(self, bundle):
bundle.data['email'] = bundle.obj.user.email
bundle.data['username'] = bundle.obj.user.username
2013-02-10 21:40:11 -08:00
bundle.data['user_id'] = bundle.obj.user.id
bundle.data['api_key'] = bundle.obj.user.api_key.key
2013-02-10 21:40:11 -08:00
bundle.data['is_pro'] = bundle.obj.user.profile.is_pro
return bundle
2015-07-24 18:28:31 -07:00
2011-12-25 13:00:41 -08:00
class PrivateUserResource(ModelResource):
2015-07-24 18:28:31 -07:00
profile = fields.ForeignKey(PrivateUserProfileResource, 'profile',
full=False)
2011-12-25 13:00:41 -08:00
class Meta:
queryset = User.objects.all()
resource_name = 'user'
2013-02-10 19:16:15 -08:00
fields = ['id', 'username', 'email']
2011-12-25 13:00:41 -08:00
include_absolute_url = True
allowed_methods = ['get']
list_allowed_methods = []
2012-01-29 17:48:17 -08:00
authentication = ApiKeyAuthentication()
authorization = PrivateUserAuthorization()
always_return_data = True
2012-08-27 09:01:37 -07:00
max_limit = 200
2011-12-25 13:00:41 -08:00
cache = SimpleCache()
2012-04-13 10:13:19 -07:00
def dehydrate(self, bundle):
2015-07-24 18:28:31 -07:00
bundle.data['email_md5'] = hashlib \
.md5(bundle.obj.email.lower()) \
.hexdigest()
bundle.data['is_pro'] = bundle.obj.profile.is_pro
2015-01-03 08:08:47 -08:00
bundle.data['stats'] = {
2015-07-24 18:28:31 -07:00
'public_snipts': Snipt.objects.filter(user=bundle.obj.id,
public=True).count(),
'private_snipts': Snipt.objects.filter(user=bundle.obj.id,
public=False).count(),
2015-01-03 08:08:47 -08:00
'total_snipts': Snipt.objects.filter(user=bundle.obj.id).count(),
2015-07-24 18:28:31 -07:00
'total_views': Snipt.objects.filter(user=bundle.obj.id).aggregate(
models.Sum('views'))['views__sum']
2015-01-03 08:08:47 -08:00
}
user_snipts = Snipt.objects.filter(user=bundle.obj)
user_tags = [
snipt['tags'] for snipt in user_snipts.values('tags').distinct()
]
tags = [
tag['name'] for tag in
Tag.objects.filter(id__in=user_tags).values('name').distinct()
]
bundle.data['tags'] = tags
2015-07-24 18:28:31 -07:00
bundle.data['lexers'] = [
snipt['lexer'] for snipt in user_snipts
2015-07-24 18:28:31 -07:00
.values('lexer').distinct()]
2012-04-13 10:13:19 -07:00
return bundle
2015-07-24 18:28:31 -07:00
2011-12-22 20:36:06 -08:00
class PrivateSniptResource(ModelResource):
2011-12-25 13:00:41 -08:00
user = fields.ForeignKey(PrivateUserResource, 'user', full=True)
2012-01-29 20:49:14 -08:00
tags_list = ListField()
2011-12-25 13:00:41 -08:00
2011-12-22 20:36:06 -08:00
class Meta:
2011-12-24 12:08:49 -08:00
queryset = Snipt.objects.all().order_by('-created')
2011-12-22 20:36:06 -08:00
resource_name = 'snipt'
2015-07-24 18:28:31 -07:00
fields = ['id', 'title', 'slug', 'lexer', 'code', 'description',
'line_count', 'stylized', 'key', 'public', 'blog_post',
'created', 'modified', 'publish_date', 'meta']
2011-12-22 20:36:06 -08:00
include_absolute_url = True
2012-01-30 19:20:31 -08:00
detail_allowed_methods = ['get', 'patch', 'put', 'delete']
2012-01-29 17:48:17 -08:00
list_allowed_methods = ['get', 'post']
authentication = ApiKeyAuthentication()
authorization = PrivateSniptAuthorization()
2014-05-04 19:47:15 -07:00
validation = SniptValidation()
2015-07-24 18:28:31 -07:00
ordering = ['created', 'modified']
always_return_data = True
2015-09-15 08:57:57 -07:00
max_limit = 200
2012-01-29 19:04:52 -08:00
cache = SimpleCache()
2011-12-22 20:36:06 -08:00
def dehydrate(self, bundle):
bundle.data['embed_url'] = bundle.obj.get_embed_url()
2013-03-15 11:19:28 -07:00
bundle.data['raw_url'] = bundle.obj.get_raw_url()
2012-01-30 19:20:31 -08:00
bundle.data['tags_list'] = edit_string_for_tags(bundle.obj.tags.all())
bundle.data['full_absolute_url'] = bundle.obj.get_full_absolute_url()
2015-07-24 18:28:31 -07:00
bundle.data['description_rendered'] = \
linebreaksbr(urlize(bundle.obj.description))
2013-08-13 11:20:46 -07:00
bundle.data['views'] = bundle.obj.views
bundle.data['favs'] = bundle.obj.favs()
2012-09-17 10:26:54 -07:00
2012-05-27 11:51:21 -07:00
if bundle.data['publish_date']:
2015-07-24 18:28:31 -07:00
bundle.data['publish_date'] = \
date(bundle.data['publish_date'], 'M d, Y \\a\\t h:i A')
2012-05-27 11:51:21 -07:00
2011-12-22 20:36:06 -08:00
return bundle
2013-03-24 15:41:57 -07:00
def obj_create(self, bundle, **kwargs):
2012-01-30 19:20:31 -08:00
bundle.data['tags_list'] = bundle.data.get('tags')
2012-01-29 20:49:14 -08:00
bundle.data['tags'] = ''
2012-05-24 19:20:06 -07:00
2012-05-29 07:49:42 -07:00
if 'blog_post' in bundle.data:
bundle = self._clean_publish_date(bundle)
2012-05-27 11:51:21 -07:00
2015-07-24 18:28:31 -07:00
return super(PrivateSniptResource, self) \
.obj_create(bundle,
user=bundle.request.user, **kwargs)
2011-12-22 20:36:06 -08:00
2013-03-24 15:41:57 -07:00
def obj_update(self, bundle, **kwargs):
bundle.data['user'] = bundle.request.user
bundle.data['created'] = None
bundle.data['modified'] = None
2012-07-08 20:55:18 -07:00
2012-07-04 08:03:09 -07:00
if type(bundle.data['tags']) in (str, unicode):
2012-01-30 19:20:31 -08:00
bundle.data['tags_list'] = bundle.data['tags']
else:
bundle.data['tags_list'] = ''
bundle.data['tags'] = ''
2012-05-24 19:20:06 -07:00
2012-05-29 07:49:42 -07:00
if 'blog_post' in bundle.data:
bundle = self._clean_publish_date(bundle)
2012-05-27 11:51:21 -07:00
2015-07-24 18:28:31 -07:00
return super(PrivateSniptResource, self) \
.obj_update(bundle,
user=bundle.request.user, **kwargs)
2012-01-30 19:20:31 -08:00
2012-05-27 11:51:21 -07:00
def _clean_publish_date(self, bundle):
2012-07-05 18:22:45 -07:00
if bundle.data['blog_post'] and 'publish_date' not in bundle.data:
bundle.data['publish_date'] = datetime.datetime.now()
elif bundle.data['publish_date'] == '':
2012-05-27 11:51:21 -07:00
bundle.data['publish_date'] = datetime.datetime.now()
elif bundle.data['blog_post']:
2013-03-15 11:35:31 -07:00
c = pdt.Constants()
2012-05-27 11:51:21 -07:00
p = pdt.Calendar(c)
publish_date, result = p.parse(bundle.data['publish_date'])
if result != 0:
publish_date = time.strftime("%Y-%m-%d %H:%M:%S", publish_date)
else:
publish_date = datetime.datetime.now()
bundle.data['publish_date'] = publish_date
elif not bundle.data['blog_post']:
bundle.data['publish_date'] = None
return bundle
2011-12-25 13:00:41 -08:00
def build_filters(self, filters=None):
if filters is None:
filters = {}
orm_filters = super(PrivateSniptResource, self).build_filters(filters)
if 'tag' in filters:
tag = Tag.objects.get(pk=filters['tag'])
tagged_items = tag.taggit_taggeditem_items.all()
orm_filters['pk__in'] = [i.object_id for i in tagged_items]
2012-05-09 14:18:09 -07:00
if 'q' in filters:
2015-08-28 09:37:56 -07:00
user = User.objects.get(username=filters['username'])
sqs = SearchQuerySet().filter(author=user, content=filters['q'])
2012-05-09 14:18:09 -07:00
orm_filters['pk__in'] = [i.pk for i in sqs]
2011-12-25 13:00:41 -08:00
return orm_filters
2012-01-29 20:49:14 -08:00
def save_m2m(self, bundle):
tags = bundle.data.get('tags_list', [])
2012-01-30 19:20:31 -08:00
if tags != '':
bundle.obj.tags.set(*parse_tags(tags))
2012-07-08 20:55:18 -07:00
else:
bundle.obj.tags.set()
2012-07-04 08:03:09 -07:00
2015-07-24 18:28:31 -07:00
2012-04-12 19:04:37 -07:00
class PrivateFavoriteResource(ModelResource):
user = fields.ForeignKey(PrivateUserResource, 'user', full=True)
snipt = fields.ForeignKey(PrivateSniptResource, 'snipt', full=False)
class Meta:
queryset = Favorite.objects.all().order_by('-created')
resource_name = 'favorite'
2015-07-24 18:28:31 -07:00
fields = ['id']
2012-04-12 19:04:37 -07:00
validation = FavoriteValidation()
detail_allowed_methods = ['get', 'post', 'delete']
2015-07-24 18:28:31 -07:00
list_allowed_methods = ['get', 'post']
2012-04-12 19:04:37 -07:00
authentication = ApiKeyAuthentication()
authorization = PrivateFavoriteAuthorization()
2015-07-24 18:28:31 -07:00
ordering = ['created']
2012-04-12 19:04:37 -07:00
always_return_data = True
2012-08-27 09:01:37 -07:00
max_limit = 200
2012-04-12 19:04:37 -07:00
cache = SimpleCache()
def dehydrate(self, bundle):
bundle.data['snipt'] = '/api/public/snipt/{}/'.format(
2015-07-24 18:28:31 -07:00
bundle.obj.snipt.pk)
return bundle
2013-03-24 15:41:57 -07:00
def obj_create(self, bundle, **kwargs):
bundle.data['user'] = bundle.request.user
2012-04-12 19:04:37 -07:00
bundle.data['snipt'] = Snipt.objects.get(pk=bundle.data['snipt'])
2015-07-24 18:28:31 -07:00
return super(PrivateFavoriteResource, self) \
.obj_create(bundle, user=bundle.request.user, **kwargs)