snipt/snipts/api.py

566 lines
18 KiB
Python
Raw Permalink 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
2016-05-09 09:35:49 -07:00
import requests
2015-07-24 18:28:31 -07:00
import time
2012-05-27 11:51:21 -07:00
2015-07-24 18:39:25 -07:00
from accounts.models import UserProfile
2016-05-09 09:35:49 -07:00
from django.conf import settings
2015-07-24 18:39:25 -07:00
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
2015-07-24 18:39:25 -07:00
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.is_authorized_user(bundle.request.user)
def create_list(self, object_list, bundle):
raise Unauthorized()
def create_detail(self, object_list, bundle):
user = bundle.obj.user
if user == bundle.request.user:
return True
if user.profile.is_a_team:
return user.team.user_is_member(bundle.request.user)
return False
def update_list(self, object_list, bundle):
raise Unauthorized()
def update_detail(self, object_list, bundle):
return bundle.obj.is_authorized_user(bundle.request.user)
def delete_list(self, object_list, bundle):
raise Unauthorized()
def delete_detail(self, object_list, bundle):
2015-10-18 12:19:46 -07:00
return bundle.obj.is_authorized_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 = {}
2019-01-23 15:52:55 -08:00
snipt = bundle.data["snipt"]
2012-04-12 19:04:37 -07:00
2019-01-23 15:52:55 -08:00
if Favorite.objects.filter(user=bundle.request.user, snipt=snipt).count():
errors = "User has already favorited this snipt."
2012-04-12 19:04:37 -07:00
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 = {}
2019-01-23 15:52:55 -08:00
if len(bundle.data["title"]) > 255:
errors = "Title must be 255 characters or less."
2016-05-09 09:35:49 -07:00
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]:
2019-01-23 15:52:55 -08:00
if not re.match("^[ A-Za-z0-9\/\@\._-]*$", bundle.data[field]):
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()
2019-01-23 15:52:55 -08:00
resource_name = "user"
fields = ["id", "username"]
2011-10-02 13:16:58 -07:00
include_absolute_url = True
2019-01-23 15:52:55 -08:00
allowed_methods = ["get"]
filtering = {"username": ["contains", "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):
2019-01-23 15:52:55 -08:00
bundle.data["snipts"] = "/api/public/snipt/?user=%d" % bundle.obj.id
bundle.data["email_md5"] = hashlib.md5(
bundle.obj.email.lower().encode("utf-8")
).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()
2019-01-23 15:52:55 -08:00
queryset = queryset.annotate(count=models.Count("taggit_taggeditem_items__id"))
queryset = queryset.order_by("-count", "name")
resource_name = "tag"
fields = ["id", "name"]
allowed_methods = ["get"]
2014-05-26 14:28:13 -07:00
max_limit = 200
cache = SimpleCache()
2016-11-01 09:59:35 -07:00
def build_filters(self, filters=None, **kwargs):
2014-05-26 14:28:13 -07:00
if filters is None:
filters = {}
2014-05-26 14:28:13 -07:00
orm_filters = super(PublicTagResource, self).build_filters(filters)
2019-01-23 15:52:55 -08: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):
2019-01-23 15:52:55 -08:00
bundle.data["absolute_url"] = "/public/tag/%s/" % bundle.obj.slug
bundle.data["snipts"] = "/api/public/snipt/?tag=%d" % bundle.obj.id
2014-05-26 14:28:13 -07:00
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):
2019-01-23 15:52:55 -08:00
user = fields.ForeignKey(PublicUserResource, "user", full=True)
tags = fields.ToManyField(PublicTagResource, "tags", related_name="tag", full=True)
2011-10-01 10:23:05 -07:00
class Meta:
2019-01-23 15:52:55 -08:00
queryset = Snipt.objects.filter(public=True).order_by("-created")
resource_name = "snipt"
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
2019-01-23 15:52:55 -08:00
allowed_methods = ["get"]
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):
2019-01-23 15:52:55 -08:00
bundle.data["embed_url"] = bundle.obj.get_embed_url()
bundle.data["raw_url"] = bundle.obj.get_raw_url()
bundle.data["full_absolute_url"] = bundle.obj.get_full_absolute_url()
bundle.data["description_rendered"] = linebreaksbr(
urlize(bundle.obj.description)
)
log_entries = bundle.obj.sniptlogentry_set.all()
bundle_log_entries = []
for entry in log_entries:
2019-01-23 15:52:55 -08:00
bundle_log_entries.append(
{
"created": entry.created,
"user": entry.user,
"code": entry.code,
"diff": entry.diff,
}
)
2019-01-23 15:52:55 -08:00
bundle.data["log_entries"] = bundle_log_entries
2019-01-23 15:52:55 -08:00
if "omit_code" in bundle.request.GET:
del bundle.data["code"]
2019-01-23 15:52:55 -08:00
if "omit_stylized" in bundle.request.GET:
del bundle.data["stylized"]
2015-04-03 09:27:02 -07:00
2011-10-01 16:09:59 -07:00
return bundle
2011-10-02 15:38:20 -07:00
2016-11-01 09:59:35 -07:00
def build_filters(self, filters=None, **kwargs):
2011-10-02 15:38:20 -07:00
if filters is None:
filters = {}
orm_filters = super(PublicSniptResource, self).build_filters(filters)
2019-01-23 15:52:55 -08:00
if "tag" in filters:
tag = Tag.objects.get(pk=filters["tag"])
2011-10-02 15:38:20 -07:00
tagged_items = tag.taggit_taggeditem_items.all()
2019-01-23 15:52:55 -08:00
orm_filters["pk__in"] = [i.object_id for i in tagged_items]
2011-10-02 15:38:20 -07:00
# if "q" in filters:
# sqs = SearchQuerySet().auto_query(filters["q"])
# orm_filters["pk__in"] = [i.pk for i in sqs]
2012-05-09 14:18:09 -07:00
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()
2019-01-23 15:52:55 -08:00
resource_name = "profile"
excludes = ["is_pro"]
validation = UserProfileValidation()
include_absolute_url = False
2019-01-23 15:52:55 -08:00
allowed_methods = ["get", "put"]
list_allowed_methods = []
authentication = ApiKeyAuthentication()
authorization = PrivateUserProfileAuthorization()
always_return_data = True
max_limit = 200
def dehydrate(self, bundle):
2019-01-23 15:52:55 -08:00
bundle.data["email"] = bundle.obj.user.email
bundle.data["username"] = bundle.obj.user.username
bundle.data["user_id"] = bundle.obj.user.id
bundle.data["api_key"] = bundle.obj.user.api_key.key
return bundle
2015-07-24 18:28:31 -07:00
2011-12-25 13:00:41 -08:00
class PrivateUserResource(ModelResource):
2019-01-23 15:52:55 -08:00
profile = fields.ForeignKey(PrivateUserProfileResource, "profile", full=False)
2011-12-25 13:00:41 -08:00
class Meta:
queryset = User.objects.all()
2019-01-23 15:52:55 -08:00
resource_name = "user"
fields = ["id", "username", "email"]
2011-12-25 13:00:41 -08:00
include_absolute_url = True
2019-01-23 15:52:55 -08:00
allowed_methods = ["get"]
2011-12-25 13:00:41 -08:00
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):
2019-01-23 15:52:55 -08:00
bundle.data["email_md5"] = hashlib.md5(
bundle.obj.email.lower().encode("utf-8")
).hexdigest()
bundle.data["stats"] = {
"public_snipts": Snipt.objects.filter(
user=bundle.obj.id, public=True
).count(),
"private_snipts": Snipt.objects.filter(
user=bundle.obj.id, public=False
).count(),
"total_snipts": Snipt.objects.filter(user=bundle.obj.id).count(),
"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)
2019-01-23 15:52:55 -08:00
user_tags = [snipt["tags"] for snipt in user_snipts.values("tags").distinct()]
tags = [
2019-01-23 15:52:55 -08:00
tag["name"]
for tag in Tag.objects.filter(id__in=user_tags).values("name").distinct()
]
2019-01-23 15:52:55 -08:00
bundle.data["tags"] = tags
2019-01-23 15:52:55 -08:00
bundle.data["lexers"] = [
snipt["lexer"] for snipt in user_snipts.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):
2019-01-23 15:52:55 -08:00
user = fields.ForeignKey(PrivateUserResource, "user", full=True)
last_user_saved = fields.ForeignKey(
PrivateUserResource, "last_user_saved", null=True, full=False
)
2012-01-29 20:49:14 -08:00
tags_list = ListField()
2019-01-23 15:52:55 -08:00
tags = fields.ToManyField(PublicTagResource, "tags", related_name="tag", full=True)
2011-12-25 13:00:41 -08:00
2011-12-22 20:36:06 -08:00
class Meta:
2019-01-23 15:52:55 -08:00
queryset = Snipt.objects.all().order_by("-created")
resource_name = "snipt"
fields = [
"id",
"title",
"slug",
"lexer",
"code",
"description",
"line_count",
"stylized",
"key",
"public",
"secure",
"blog_post",
"created",
"modified",
"publish_date",
"meta",
]
2011-12-22 20:36:06 -08:00
include_absolute_url = True
2019-01-23 15:52:55 -08:00
detail_allowed_methods = ["get", "patch", "put", "delete"]
list_allowed_methods = ["get", "post"]
2012-01-29 17:48:17 -08:00
authentication = ApiKeyAuthentication()
authorization = PrivateSniptAuthorization()
2014-05-04 19:47:15 -07:00
validation = SniptValidation()
2019-01-23 15:52:55 -08: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):
2019-01-23 15:52:55 -08:00
bundle.data["embed_url"] = bundle.obj.get_embed_url()
bundle.data["raw_url"] = bundle.obj.get_raw_url()
bundle.data["tags_list"] = edit_string_for_tags(bundle.obj.tags.all())
bundle.data["full_absolute_url"] = bundle.obj.get_full_absolute_url()
bundle.data["description_rendered"] = linebreaksbr(
urlize(bundle.obj.description)
)
bundle.data["views"] = bundle.obj.views
bundle.data["favs"] = bundle.obj.favs()
if bundle.data["publish_date"]:
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
log_entries = bundle.obj.sniptlogentry_set.all()
bundle_log_entries = []
for entry in log_entries:
2019-01-23 15:52:55 -08:00
bundle_log_entries.append(
{
"created": entry.created,
"user": entry.user,
"code": entry.code,
"diff": entry.diff,
}
)
2019-01-23 15:52:55 -08:00
bundle.data["log_entries"] = bundle_log_entries
2011-12-22 20:36:06 -08:00
return bundle
2013-03-24 15:41:57 -07:00
def obj_create(self, bundle, **kwargs):
2019-01-23 15:52:55 -08:00
bundle.data["last_user_saved"] = bundle.request.user
bundle.data["tags_list"] = bundle.data.get("tags")
bundle.data["tags"] = []
if "intended_user" in bundle.data:
bundle.data["user"] = User.objects.get(
username=bundle.data["intended_user"]
)
2015-11-10 08:03:48 -08:00
else:
2019-01-23 15:52:55 -08:00
bundle.data["user"] = bundle.request.user
2012-05-24 19:20:06 -07:00
2019-01-23 15:52:55 -08:00
if "blog_post" in bundle.data:
2012-05-29 07:49:42 -07:00
bundle = self._clean_publish_date(bundle)
2012-05-27 11:51:21 -07:00
2019-01-23 15:52:55 -08:00
return super(PrivateSniptResource, self).obj_create(bundle, **kwargs)
2011-12-22 20:36:06 -08:00
2013-03-24 15:41:57 -07:00
def obj_update(self, bundle, **kwargs):
2019-01-23 15:52:55 -08:00
instance = Snipt.objects.get(pk=bundle.data["id"])
2019-01-23 15:52:55 -08:00
if instance.user.profile.is_a_team:
user = instance.user
else:
user = bundle.request.user
2019-01-23 15:52:55 -08:00
bundle.data["created"] = None
bundle.data["last_user_saved"] = bundle.request.user
bundle.data["modified"] = None
bundle.data["user"] = user
2012-07-08 20:55:18 -07:00
2019-01-23 15:52:55 -08:00
if type(bundle.data["tags"]) == str or type(bundle.data["tags"]) == unicode:
bundle.data["tags_list"] = bundle.data["tags"]
2012-01-30 19:20:31 -08:00
else:
2019-01-23 15:52:55 -08:00
bundle.data["tags_list"] = ""
bundle.data["tags"] = ""
2012-05-24 19:20:06 -07:00
2019-01-23 15:52:55 -08:00
if "blog_post" in bundle.data:
2012-05-29 07:49:42 -07:00
bundle = self._clean_publish_date(bundle)
2012-05-27 11:51:21 -07:00
2019-01-23 15:52:55 -08:00
return super(PrivateSniptResource, self).obj_update(bundle, **kwargs)
2012-01-30 19:20:31 -08:00
2012-05-27 11:51:21 -07:00
def _clean_publish_date(self, bundle):
2019-01-23 15:52:55 -08: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"] == "":
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)
2019-01-23 15:52:55 -08:00
publish_date, result = p.parse(bundle.data["publish_date"])
2012-05-27 11:51:21 -07:00
if result != 0:
2019-01-23 15:52:55 -08:00
publish_date = time.strftime("%Y-%m-%d %H:%M:%S", publish_date)
2012-05-27 11:51:21 -07:00
else:
publish_date = datetime.datetime.now()
2019-01-23 15:52:55 -08:00
bundle.data["publish_date"] = publish_date
elif not bundle.data["blog_post"]:
bundle.data["publish_date"] = None
2012-05-27 11:51:21 -07:00
return bundle
2016-11-01 09:59:35 -07:00
def build_filters(self, filters=None, **kwargs):
2011-12-25 13:00:41 -08:00
if filters is None:
filters = {}
orm_filters = super(PrivateSniptResource, self).build_filters(filters)
2019-01-23 15:52:55 -08:00
if "tag" in filters:
tag = Tag.objects.get(pk=filters["tag"])
2011-12-25 13:00:41 -08:00
tagged_items = tag.taggit_taggeditem_items.all()
2019-01-23 15:52:55 -08:00
orm_filters["pk__in"] = [i.object_id for i in tagged_items]
2011-12-25 13:00:41 -08:00
# if "q" in filters:
# user = User.objects.get(username=filters["username"])
# sqs = SearchQuerySet().filter(author=user, content=filters["q"])
# orm_filters["pk__in"] = [i.pk for i in sqs]
2012-05-09 14:18:09 -07:00
2011-12-25 13:00:41 -08:00
return orm_filters
2012-01-29 20:49:14 -08:00
def save_m2m(self, bundle):
2019-01-23 15:52:55 -08:00
tags = bundle.data.get("tags_list", [])
if tags != "":
2012-01-30 19:20:31 -08:00
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):
2019-01-23 15:52:55 -08:00
user = fields.ForeignKey(PrivateUserResource, "user", full=True)
snipt = fields.ForeignKey(PrivateSniptResource, "snipt", full=False)
2012-04-12 19:04:37 -07:00
class Meta:
2019-01-23 15:52:55 -08:00
queryset = Favorite.objects.all().order_by("-created")
resource_name = "favorite"
fields = ["id"]
2012-04-12 19:04:37 -07:00
validation = FavoriteValidation()
2019-01-23 15:52:55 -08:00
detail_allowed_methods = ["get", "post", "delete"]
list_allowed_methods = ["get", "post"]
2012-04-12 19:04:37 -07:00
authentication = ApiKeyAuthentication()
authorization = PrivateFavoriteAuthorization()
2019-01-23 15:52:55 -08: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):
2019-01-23 15:52:55 -08:00
bundle.data["snipt"] = "/api/public/snipt/{}/".format(bundle.obj.snipt.pk)
return bundle
2013-03-24 15:41:57 -07:00
def obj_create(self, bundle, **kwargs):
2019-01-23 15:52:55 -08:00
bundle.data["user"] = bundle.request.user
bundle.data["snipt"] = Snipt.objects.get(pk=bundle.data["snipt"])
return super(PrivateFavoriteResource, self).obj_create(
bundle, user=bundle.request.user, **kwargs
)