drf-access-policy icon indicating copy to clipboard operation
drf-access-policy copied to clipboard

`view.get_object()` raises AssertionError inside condition method

Open jdrempel opened this issue 4 years ago • 1 comments

Hi there.

I'm using view.get_object() as shown in the documentation but in certain cases there is an assertion failing (lookup_url_kwarg in self.kwargs) inside of get_object(). In the example I share here, it's on the list action, where the url follows the pattern: /quiz/?course=<pk>. In another case, however, it's when I use the create action on a different model.

Expected view QuizViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly.

Here is my policy:

statements = [
  {
    'action': ['retrieve'],
    'principal': 'authenticated',
    'effect': 'allow',
    'condition_expression': 'is_in_course and accessible_if_student'
  }
]

The condition methods:

def is_in_course(self, request, view, action):
  user = request.user
  quiz = view.get_object()  # raises AssertionError on list action
  return user in course.admins.all() or user in course.instructors.all() or user in course.graders.all() \
    or user in course.students.all() or user in course.guests.all()

def accessible_if_student(self, request, view, action):
  user = request.user
  quiz = view.get_object()
  course = quiz.course

  if user in course.students.all():
    return True
  return quiz.published and user in quiz.students.all()

So clearly I'm missing the pk but I'm not exactly sure how I'm supposed to provide that. Any ideas?

jdrempel avatar Aug 24 '21 04:08 jdrempel

Hey buddy, have you already solved?

If not, you can create specific statements on access policy class with conditions to each action, or make a if-else statement where get_object is called according to the action, or refactor your code to remove quiz where isn't being used, among other similar solutions.

helderlgoliveira avatar Oct 28 '21 01:10 helderlgoliveira