Home > database >  DRF Framework - allow User CRUD on another Users related field if they are in relationship through a
DRF Framework - allow User CRUD on another Users related field if they are in relationship through a

Time:03-26

I have a model Application that has fields applicant = ForeignKey('User'...) and coapplicant = ForeignKey('User'...).

There is also a model Income that has field user = ForeignKey('User'....

I want to allow User A to create, edit, delete Income objects of User B if A and B are in a relationship through Application.

That means:

User A can CRUD Incomes of User B and vice-versa if there is such Application object where A is an applicant and B co-applicant or A is a co-applicant and B applicant.

Do you know how to make that work?

CodePudding user response:

You can write custom permission something like this:

from django.db.models import F

class IsOwnerOrCoapplicant(permissions.BasePermission):
    """
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        if obj.user == request.user:
            return True

        # If application with both users exists return true,
        # exclude cases when applicant and coapplicant are the same just in case   
        if Application.objects.filter(applicant__in=[obj.user, request.user], coapplicant__in=[obj.user, request.user]).exclude(applicant=F('coapplicant')).exists()
           return True
        return False 

CodePudding user response:

you can define a many-to-many relationship between User A and other Users like B (which I am going to call coapplicants from now) using the Application model. and Django through fields

for example:

from Django import models

class User(models.Model):
    ...
    ....
    coapplicants = models.ManyToManyField(
        'User',
        through='Application',
        through_fields=('applicant', 'coapplicant'),
    )

class Application(models.Model):
    applicant= models.ForeignKey('User',...)
    coapplicant = models.ForeignKey('User'...)
    

if you want both A and B to be in this relationship, otherwise just use one of applicant or coapplicant in through_fields. check documentation here

now that you defined a relationship between them, you can use Django rest object permissions to give User B access to edit Income objects belonging to User A. documentation here

from rest_framework import permissions

class IsOwnerOrCoapplicant(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):

        # assuming Income instance has an attribute named `owner`.
        return obj.owner == request.user or request.user.coapplicants.filter(id=obj.owner.id).exists()

if you add this permission to a ViewSet that works with Income objects, obj argument passed to has_object_permission function is an Income instance.

  • Related