0

I am using django-guardian to implement object-level permissions in my tastypie api and I would like to be able to toggle an instance of a resource's permissions between private, and public.

For example, I have an Event resource. When a User creates an Event, the Event.creator is set to the User instance. I use a a post_save signal on the Event to give object-level permissions the User who created it - making it private to the creator.

I want a User to be able toggle the permissions level for the Event to allow all users to be able to access it - aka change the Event from private to public (and back again).

What is the best way to handle this? I'd like to stick with guardian if possible, but am not married to it. Here are some snippets of code to help illustrate:

models.py

class UserProfile(models.Model):    
    user = models.OneToOneField(User, primary_key=True)
    events = models.ManyToManyField('myapp.Event', through="myapp.EventMembership", null=True, blank=True)

class Event(models.Model):
    name = models.CharField(max_length=64)
    creator = models.ForeignKey('myapp.UserProfile', related_name="creator")

resources.py

class EventResource(ModelResource):
    class Meta:
        queryset = Event.objects.all()
        resource_name = 'events'
        authentication = ApiKeyAuthentication()
        authorization = GuardianAuthorization(
            create_permission_code  = "myapp.add_event",
            view_permission_code    = "myapp.view_event",
            update_permission_code  = "myapp.change_event",
            delete_permission_code  = "myapp.delete_event"
        )
        always_return_data = True

    creator = fields.ForeignKey('myapp.UserProfile', 'creator', full=True)

    def hydrate(self, bundle, **kwargs):
        bundle.obj.creator = UserProfile.objects.get(user_id=bundle.request.user)
        return bundle

signals.py

@receiver(post_save, sender=User)
def allow_user_to_create_events(sender, instance, **kwargs):
    if not instance:
        return None

    if kwargs.get('created'):
        ApiKey.objects.create(user=instance)

    # give newly created user permissions to create events
    add_permission(instance, "myapp.add_event", Event)

@receiver(post_save, sender=Event)
def allow_user_to_edit_events(sender, instance, *args, **kwargs):
    if not instance or not isinstance(instance, Event):
        return None

    # assign_perm is a guardian shortcut
    assign_perm("myapp.view_event", instance.creator.user, instance)
    assign_perm("myapp.edit_event", instance.creator.user, instance)
    assign_perm("myapp.delete_event", instance.creator.user, instance)

Thanks for your time and help!

Note: I am using the guardian-authorization in my tastypie resources. However, I think my question is more of a guardian question, and not so much about it's use with tastypie.

gthmb
  • 808
  • 5
  • 10

1 Answers1

0

I don't know how guaridan-authorization works. But in your authorization class you class you can always do a lookup and return True if the object has been set to public.

dan-klasson
  • 13,734
  • 14
  • 63
  • 101