I am sure that this is fairly straightforward, but I have scoured the documentation and I can't quite figure out how to do this.
I have extended my User
class to have two ManyToMany relationships to other users: trainers
and teammates
.
If a user owns an object (defined by a user
ForeignKey on the model), then that user should be able to GET
, POST
, PUT
, PATCH
, and DELETE
. I have set up these endpoints with ModelViewSet
. If a user is a trainer of the owner, they should have the same privileges. If a user is a teammate of the owner, they should only be able to GET
.
In a list view of these objects, a user should only see the objects they own and the objects where they are a trainer or teammate of the owner. If they try and access a detail view of an object where they are not the friend or the teammate of the owner, it should return a 403.
I extended BasePermission
as follows to try and create this behavior -- I then added it to the ModelViewSet
where I wanted this behavior.
class TrainerAndOwnerOrTeammate(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
user = request.user
owner = obj.user
if user == owner:
return True
if user in owner.trainers.all():
return True
if user in owner.teammates.all():
return request.method in permissions.SAFE_METHODS
return False
Since the REST Framework documentation specifies that this isn't run on a per-object basis for list views, I overrode get_queryset
to filter by the request user.
The issue is now I get a 404 error, not a 403, if I try and access a detail view I shouldn't have access to. I understand why that's happening, but is there a way to fix it?