mirror of
https://github.com/pinry/pinry.git
synced 2025-11-14 00:55:43 +01:00
As pointed in issue #75 we should get away with just checking if the pin submitter is the currently logged in user. Assuming that we can implement authorization for updating and deleting pins rather easily by subclassing DjangoAuthorization so it passes the object to the Authorization backend.
123 lines
4.1 KiB
Python
123 lines
4.1 KiB
Python
from tastypie import fields
|
|
from tastypie.authorization import DjangoAuthorization
|
|
from tastypie.exceptions import Unauthorized
|
|
from tastypie.resources import ModelResource
|
|
from django_images.models import Thumbnail
|
|
|
|
from pinry.core.models import User
|
|
from pinry.pins.models import Image, Pin
|
|
|
|
|
|
class PinryAuthorization(DjangoAuthorization):
|
|
"""
|
|
Pinry-specific Authorization backend with object-level permission checking.
|
|
"""
|
|
def update_detail(self, object_list, bundle):
|
|
klass = self.base_checks(bundle.request, bundle.obj.__class__)
|
|
|
|
if klass is False:
|
|
raise Unauthorized("You are not allowed to access that resource.")
|
|
|
|
permission = '%s.change_%s' % (klass._meta.app_label, klass._meta.module_name)
|
|
|
|
if not bundle.request.user.has_perm(permission, bundle.obj):
|
|
raise Unauthorized("You are not allowed to access that resource.")
|
|
|
|
return True
|
|
|
|
def delete_detail(self, object_list, bundle):
|
|
klass = self.base_checks(bundle.request, bundle.obj.__class__)
|
|
|
|
if klass is False:
|
|
raise Unauthorized("You are not allowed to access that resource.")
|
|
|
|
permission = '%s.delete_%s' % (klass._meta.app_label, klass._meta.module_name)
|
|
|
|
if not bundle.request.user.has_perm(permission, bundle.obj):
|
|
raise Unauthorized("You are not allowed to access that resource.")
|
|
|
|
return True
|
|
|
|
|
|
class UserResource(ModelResource):
|
|
gravatar = fields.CharField(readonly=True)
|
|
|
|
def dehydrate_gravatar(self, bundle):
|
|
return bundle.obj.gravatar
|
|
|
|
class Meta:
|
|
list_allowed_methods = ['get']
|
|
queryset = User.objects.all()
|
|
resource_name = 'user'
|
|
fields = ['username']
|
|
include_resource_uri = False
|
|
|
|
|
|
def filter_generator_for(size):
|
|
def wrapped_func(bundle, **kwargs):
|
|
return Thumbnail.objects.get_or_create_at_size(bundle.obj.pk, size, **kwargs)
|
|
return wrapped_func
|
|
|
|
|
|
class ThumbnailResource(ModelResource):
|
|
class Meta:
|
|
list_allowed_methods = ['get']
|
|
fields = ['image', 'width', 'height']
|
|
queryset = Thumbnail.objects.all()
|
|
resource_name = 'thumbnail'
|
|
include_resource_uri = False
|
|
|
|
|
|
class ImageResource(ModelResource):
|
|
standard = fields.ToOneField(ThumbnailResource, full=True,
|
|
attribute=lambda bundle: filter_generator_for('standard')(bundle))
|
|
thumbnail = fields.ToOneField(ThumbnailResource, full=True,
|
|
attribute=lambda bundle: filter_generator_for('thumbnail')(bundle))
|
|
square = fields.ToOneField(ThumbnailResource, full=True,
|
|
attribute=lambda bundle: filter_generator_for('square')(bundle))
|
|
|
|
class Meta:
|
|
fields = ['image', 'width', 'height']
|
|
include_resource_uri = False
|
|
resource_name = 'image'
|
|
queryset = Image.objects.all()
|
|
authorization = DjangoAuthorization()
|
|
|
|
|
|
class PinResource(ModelResource):
|
|
submitter = fields.ToOneField(UserResource, 'submitter', full=True)
|
|
image = fields.ToOneField(ImageResource, 'image', full=True)
|
|
tags = fields.ListField()
|
|
|
|
def hydrate_image(self, bundle):
|
|
url = bundle.data.get('url', None)
|
|
if url:
|
|
image = Image.objects.create_for_url(url)
|
|
bundle.data['image'] = '/api/v1/image/{}/'.format(image.pk)
|
|
return bundle
|
|
|
|
def dehydrate_tags(self, bundle):
|
|
return map(str, bundle.obj.tags.all())
|
|
|
|
def build_filters(self, filters=None):
|
|
if filters is None:
|
|
filters = {}
|
|
orm_filters = super(PinResource, self).build_filters(filters)
|
|
if 'tag' in filters:
|
|
orm_filters['tags__name__in'] = filters['tag'].split(',')
|
|
return orm_filters
|
|
|
|
def save_m2m(self, bundle):
|
|
tags = bundle.data.get('tags', [])
|
|
bundle.obj.tags.set(*tags)
|
|
return super(PinResource, self).save_m2m(bundle)
|
|
|
|
class Meta:
|
|
fields = ['id', 'url', 'description']
|
|
ordering = ['id']
|
|
queryset = Pin.objects.all()
|
|
resource_name = 'pin'
|
|
include_resource_uri = False
|
|
always_return_data = True
|
|
authorization = PinryAuthorization()
|