Using Django “rules” with CBVs doesn't seem to

2019-07-22 12:44发布

问题:

Each restaurant can have multiple managers.

class Restaurant(models.Model):
    ...
    managers = models.ManyToManyField(User, related_name='restaurants_which_they_manage')

Only restaurant managers can change a restaurant listing. I'm using django-rules to enforce this. I've got a predicate that creates a nice verbose "is_restaurant_manager" reference :

@rules.predicate
def is_restaurant_manager(user, restaurant):
    return user in restaurant.managers.all()

And here is the permission :

rules.add_perm('restaurants.change_restaurant', is_restaurant_manager)

Finally, here is my view :

class RestaurantChange(PermissionRequiredMixin, UpdateView):
    model = Restaurant
    permission_required = 'restaurants.change_restaurant'
    fields = ['name', 'description', ]

I've got two tests.

Test A checks that the permission works properly :

self.assertEqual(rules.has_perm('restaurants.change_restaurant', self.user, self.restaurant), True)

This first test passes successfully.

Test B attempts to access the url with a valid user :

url = reverse('restaurants__restaurant_change', kwargs={'pk': self.restaurant.key,})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)

Test B fails, as I get a redirection. This also happens if I try to access the url via the browser. The redirection goes to the login process, as though the user didn't have permission to access the view.

What's wrong with my code ?

回答1:

I was playing around with django-rules to see if it suits the needs of a project and run into the issue you added on django-rules.

After adding a pdb trace in the tests and going through your settings I noticed the following:

https://github.com/tavolia/Tavolia/blob/7aca6530a8a301b8b81999095cf7535c363dd484/_project/settings.py#L121-L124

https://github.com/tavolia/Tavolia/blob/7aca6530a8a301b8b81999095cf7535c363dd484/_project/settings.py#L142-L145

The second link is an assignment, overriding authentication backend set in the previous assignments.

By adding the 'rules.permissions.ObjectPermissionBackend' to the second set of backends, the tests pass without error.

I made a pull request on github to solve this issue: https://github.com/tavolia/Tavolia/pull/5

Cheers!