I am building Django REST as backend and Angular JS as front end.
Now I have permissions systems very advanced as 3 level
class UserSerializer(serializers.Serializer):
email = serializers.EmailField()
username = serializers.CharField(max_length=100)
field1 = serializers.CharField(max_length=100)
field2 = serializers.CharField(max_length=100)
field3 = serializers.CharField(max_length=100)
field4 = serializers.CharField(max_length=100)
Now want permissions on
User Role
view
READ / Write / Update /Delete
There are 10 Roles , 30 views like /user/view1
/user/view2
and then READ or write like
These are on field level permissions like
Field1 can be READ by Manager level on view 1
Field1 can be Edit by Manager level on view 2
Feild1 can be Delete by Admin on View 1
I am confused how can i have that sort of permission model.
I typically recommend different serializer classes for these cases, but that limits you to read and write permissions (kind of) and may not completely fit your needs.
You would create a serializer for each permission level. Lets say there are three permission levels: Admin, Manager, Normal user.
class NormalUserSerializer(ModelSerializer):
email = serializers.EmailField(read_only=True, required=True)
username = serializers.CharField(max_length=100, read_only=True)
class Meta:
fields = ("email", "username", )
class ManagerUserSerializer(NormalUserSerializer):
email = serializers.EmailField(read_only=False, required=True)
username = serializers.CharField(max_length=100, read_only=False)
class AdminSerializer(ManagerUserSerializer):
email = serializers.EmailField(read_only=False, required=False)
username = serializers.CharField(max_length=100, read_only=False)
This will limit normal users to a read-only view of the fields (read_only
is enforced by DRF). For managers, they have the ability to read and write to the fields, but they are not able to clear out the contents of the email
field (enforced by required
). Admins have the ability to read and write to all of the fields, as well as clear out the contents of the email
field.
Your view would then return the correct serializer class in get_serializer_class
based on the role of the authenticated user.
class UserViewSet(ModelViewSet):
def get_serializer_class(self):
if self.request.user.is_superuser:
return AdminUserSerializer
if self.request.user.is_staff:
return ManagerUserSerializer
return NormalUserSerializer
The other option is enforcing everything in your validate
method, and manually removing fields in the to_native
method on the serializer. If you can live with creating a serializer for each role, it is the easiest and (arguably) the most cleanest way of implementing role-based permissions on individual fields in Django REST Framework.
I have the exact same problem with a client. I created django-rest-framework-roles to automatically parameterize a given DRF method (e.g: get_queryset, get_serializer_class) over the type of user. This way you don't have to repeatedly type out conditional blocks over the types of users.
I would like to extend the library to handle the more complex permissions problems you are describing. I have these same challenges, e.g: parameterizing over Role and HTTP verb.