简体   繁体   中英

How can I make "has_object_permission( )" work?

I'm trying to create an object level permission for a user. The structure of my ddbb model is the following one:

  • A Teacher owns a Classroom (id_teacher ForeignKey)
  • A Classroom owns some Students (id_classroom ForeignKey)

I want to let the access to Student information just for the teacher who owns the classroom where the Students are registered.

Here are the API code and the permission code:

class StudentAPI(RetrieveUpdateAPIView):
    permission_classes = [GetStudentPermission, ]

    def get(self, request):
        student_ = Student.objects.get(username=request.GET['username'])
        s_student_ = StudentSerializer(student_)
        return Response(s_student_.data)
class GetStudentPermission(BasePermission):
    message = 'La información de este estudiante está restringida para usted'

    def has_object_permission(self, request, view, obj):
        cls_ = Classroom.objects.filter(id=obj.id_classroom.id).first()
        tch_ = Teacher.objects.get(classroom=cls_)
        user_ = User.objects.get(id=tch_.id_user.id)
        return bool(user_ == request.user)

It seems like permission classes is not working at all because I can access to the information of each student being registered with any user account. Thank you beforehand

As per the note in the section Custom permissions [DRF docs] :

The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call .check_object_permissions(request, obj) . If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising PermissionDenied on failure.)

Since you override get and implement it yourself check_object_permissions is never called, you can either do it yourself:

class StudentAPI(RetrieveUpdateAPIView):
    permission_classes = [GetStudentPermission, ]

    def get(self, request):
        student_ = Student.objects.get(username=request.GET['username'])
        self.check_object_permissions(self.request, student)
        s_student_ = StudentSerializer(student_)
        return Response(s_student_.data)

OR better yet your implementation of get is not much different than the builtin implementation that RetrieveUpdateAPIView already has, so you can forego overriding get and actually use the view directly:

class StudentAPI(RetrieveUpdateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    lookup_field = 'username'
    permission_classes = [GetStudentPermission, ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM