mardi 12 août 2014

python - Django : une façon plus sec pour éviter de modifier/supprimer des objets ? -Débordement de pile


After reading the permission Django documentation, I'm still confused. I'd like to prevent access for user to edit or delete objects they didn't own. I dit it this way and it works:


In views.py:


def deleteReward(request, reward_id):
reward = get_object_or_404(Reward, pk=reward_id)
if reward.owner.user != request.user: # if the user linked to the reward is not the current one
raise Exception("This reward is not yours, you can't delete it !")
#...

But I think this isn't clean and DRY for two reasons:



  1. In each editStuff and deleteStuff views, I'll have to write the same portion of code.


  2. I'm currently writing an API with Tastypie, and if the permission logic is in a view, I won't be able to re-use it. The best way to deals with seems to be to map the API permission with the Django permissions (but the code I wrote in my view has nothing to do with permissions).



Could you help me to find the right way to do? Thanks a lot.




Pass an additional parameter to get_object_or_404:


reward = get_object_or_404(Reward, pk=reward_id, owner=request.user)



Here is my working example.


1) QuerySet


class PermissionQuerySet(models.query.QuerySet):
def editable_by(self, user):
return self.filter(user=user)

def viewable_by(self, user):
return self.filter(user=user)

2) Managers


class PermissionManager(models.Manager):
def get_query_set(self):
return PermissionQuerySet(self.model)

def editable_by(self, user, *args):
return self.get_query_set().editable_by(user, *args)

def viewable_by(self, user, *args):
return self.get_query_set().viewable_by(user, *args)

3) Models


class MyModel(models.Model):
...
objects = PermissionManager()

This approach works perfectly with class based views. I see you using TastyPie. I never used it before but it seems it's uses class based views too.


This is working sample:


class MyUpdateView(UpdateView):
def post(self, request, *args, **kwargs):
self.request = request
super(MyUpdateView, self).post(request, *args, **kwargs)

def get_query_set(self):
queryset = super(MyUpdateView, self).get_query_set()
queryset = queryset.editable_by(self.request.user)
if not queryset.exists():
raise Exception("This reward is not yours, you can't delete it !")
return queryset

I think you can imagine how to use this approach in CreateView, DeleteView. And i think it is easy to implement this in TastyPie.



After reading the permission Django documentation, I'm still confused. I'd like to prevent access for user to edit or delete objects they didn't own. I dit it this way and it works:


In views.py:


def deleteReward(request, reward_id):
reward = get_object_or_404(Reward, pk=reward_id)
if reward.owner.user != request.user: # if the user linked to the reward is not the current one
raise Exception("This reward is not yours, you can't delete it !")
#...

But I think this isn't clean and DRY for two reasons:



  1. In each editStuff and deleteStuff views, I'll have to write the same portion of code.


  2. I'm currently writing an API with Tastypie, and if the permission logic is in a view, I won't be able to re-use it. The best way to deals with seems to be to map the API permission with the Django permissions (but the code I wrote in my view has nothing to do with permissions).



Could you help me to find the right way to do? Thanks a lot.



Pass an additional parameter to get_object_or_404:


reward = get_object_or_404(Reward, pk=reward_id, owner=request.user)


Here is my working example.


1) QuerySet


class PermissionQuerySet(models.query.QuerySet):
def editable_by(self, user):
return self.filter(user=user)

def viewable_by(self, user):
return self.filter(user=user)

2) Managers


class PermissionManager(models.Manager):
def get_query_set(self):
return PermissionQuerySet(self.model)

def editable_by(self, user, *args):
return self.get_query_set().editable_by(user, *args)

def viewable_by(self, user, *args):
return self.get_query_set().viewable_by(user, *args)

3) Models


class MyModel(models.Model):
...
objects = PermissionManager()

This approach works perfectly with class based views. I see you using TastyPie. I never used it before but it seems it's uses class based views too.


This is working sample:


class MyUpdateView(UpdateView):
def post(self, request, *args, **kwargs):
self.request = request
super(MyUpdateView, self).post(request, *args, **kwargs)

def get_query_set(self):
queryset = super(MyUpdateView, self).get_query_set()
queryset = queryset.editable_by(self.request.user)
if not queryset.exists():
raise Exception("This reward is not yours, you can't delete it !")
return queryset

I think you can imagine how to use this approach in CreateView, DeleteView. And i think it is easy to implement this in TastyPie.


0 commentaires:

Enregistrer un commentaire