Implement roles in django rest framework

后端 未结 2 1099
梦谈多话
梦谈多话 2021-02-09 06:48

I am building an API that should have the following kind of users

super_user - create/manage admins

admin - manage events(model) and ev

2条回答
  •  被撕碎了的回忆
    2021-02-09 07:06

    One possible solution is:

      1. Have only one User Model with role field, which defines what user role is.
      1. Create a User Group and add each group needed permissions.
      1. Add User to User Group
      1. Limit access using a Django REST Framework (later DRF) Permission Class.

    Explanation:

    1. Using only one user model is a more simple and flexible solution. You can query all users, or filtered by feature (like user role). Standart Django auth system expects one UserModel.

    2. Read more about Django user groups. See "Django Permissions Docs #1" and "Django Groups Docs #2". Also useful is "User groups and permissions".

    You need to create a group for each user role, and add needed permissions for each group. (Django has a default model permission, created automatically, look at the docs on the given links) or create the needed permission manually in the model definition.

    1. Manually or using a script, add User to the needed group by defining his role when a user is created or manually by Django Admin interface.

    2. Now everything should be ready for limited access by the user's role. You can easily limit access to the DRF View using a permission class. See more information in the "DRF Permission Docs".

    Let's define our own:

    from rest_framework.permissions import DjangoModelPermissions
    # Using DjangoModelPermissions we can limit access by checking user permissions.
    
    # Rights need only for CreateUpdateDelete actions.
    class CUDModelPermissions(DjangoModelPermissions):
      perms_map = {
          'GET': [],
          'OPTIONS': [],
          'HEAD': ['%(app_label)s.read_%(model_name)s'],
          'POST': ['%(app_label)s.add_%(model_name)s'],
          'PUT': ['%(app_label)s.change_%(model_name)s'],
          'PATCH': ['%(app_label)s.change_%(model_name)s'],
          'DELETE': ['%(app_label)s.delete_%(model_name)s'],
      }
    
    # Or you can inherit from BasePermission class and define your own rule for access
    from rest_framework.permissions import BasePermission
    
    class AdminsPermissions(BasePermission):
        allowed_user_roles = (User.SUPERVISOR, User.ADMINISTRATOR)
    
        def has_permission(self, request, view):
            is_allowed_user = request.user.role in self.allowed_user_roles
            return is_allowed_user
    
    # ----
    # on views.py
    
    from rest_framework import generics
    from .mypermissions import CUDModelPermissions, AdminsPermissions
    
    class MyViewWithPermissions(generics.RetrieveUpdateDestroyAPIView):
        permission_classes = [CUDModelPermissions, ]
        queryset = SomeModel.objects.all()
        serializer_class = MyModelSerializer
    

    You can add additional permission class to combine access limitation.

提交回复
热议问题