django extends its own permissions to support object permissions

Keywords: Linux JSON Django

Extending django's own permissions

Explain

On the basis of not rewriting its own privileges, it completes the support object privileges, which are suitable for small projects.
Amendments are welcome.

Software support

jsonfield

data base

Three new tables

from django.db import models
from django.contrib.auth.models import AbstractUser, Group ,User

from jsonfield import JSONField

class Request(models.Model):
    request = models.CharField(max_length=16, verbose_name='Request type(Capital letters)')

    class Meta:
        db_table = "request"
        verbose_name = "Request type"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.request

class RolePermission(models.Model):
    role = models.CharField(max_length=32, verbose_name='Role Groups')
    table = models.CharField(max_length=32, verbose_name='Table name')
    request = models.ManyToManyField(Request, verbose_name='request', related_name='re', )
    permission = JSONField(max_length=1024, verbose_name='Privilege Conditions')

    class Meta:
        db_table = "role_permission"
        verbose_name = "Role group permissions"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.role

class Role(models.Model):
    group = models.ForeignKey(Group, verbose_name='user group', on_delete=models.CASCADE)
    roles = models.ManyToManyField(RolePermission, verbose_name='Role group permissions', blank=True,related_name='roles' )

    class Meta:
        db_table = "role"
        verbose_name = "Role Group Relations"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.group.name
system/models
 Role role group relationship: system user group < - > role group permissions
 Request request type: GET, POST
 RolePermission Role Group Permissions: Role Table Name Request Permission Conditions (JSON type)

The focus is on the RolePermission table.

Example

  • Take common asset asset as an example

    Table name asset field groups (grouped into dev,ops)
  • Delimitation of authority
  • New user hequan
  • New group dev

  • Add in the Request table

    GET (for read-only)
    POST (for update deletion)

  • Add in Role Permission

    Role asset-dev read-only
    Table name assset
    Request GET
    Permission condition {"groups":'dev'}

  • Add in the Role table

    System User Group dev
    Role group permission asset-dev read-only

Privilege Verification Code

import json
from system.models import Role
from functools import wraps
from django.shortcuts import HttpResponse

def role_permission_get_list(function):
    """
    //List page control rights
    :param function:
    :return:
    """

    @wraps(function)
    def wrapped(self):
        user = self.request.user
        groups = [x['name'] for x in self.request.user.groups.values()]
        request_type = self.request.method
        model = str(self.model._meta).split(".")[1]

        filter_dict = {}
        not_list = ['page', 'order_by', 'csrfmiddlewaretoken']
        for k, v in dict(self.request.GET).items():
            if [i for i in v if i != ''] and (k not in not_list):
                if '__in' in k:
                    filter_dict[k] = v
                else:
                    filter_dict[k] = v[0]

        if not user.is_superuser:
            role_groups = Role.objects.filter(group__name__in=groups).values_list('roles__table',
                                                                                  'roles__request__request',
                                                                                  'roles__permission')

            permission_dict = {}
            for i in role_groups:
                if i[0] == model and i[1] == request_type:
                    permission_dict = json.loads(i[2])

            if permission_dict:
                if filter_dict:
                    for k, v in permission_dict.items():
                        if '__in' in k:
                            k1 = k.replace('__in', '')
                        if '__gt' in k:
                            k1 = k.replace('__gt', '')
                        if '__lt' in k:
                            k1 = k.replace('__lt', '')
                        else:
                            k1 = k
                        if k1 in list(filter_dict.keys()):
                            del filter_dict[k1]

                    if filter_dict:
                        filter_dict.update(**permission_dict)
                    else:
                        print('Query condition is empty after processing,Default permissions')
                        filter_dict = permission_dict
                else:
                    print('Query condition is empty,Default permissions')
                    filter_dict = permission_dict
            else:
                print('No privileges')
                filter_dict = {'id': -1}

        self.filter_dict = filter_dict
        result = function(self)
        return result

    return wrapped

def role_permission_detail(function):
    """
    //Details page control rights
    :param function:
    :return:
    """

    @wraps(function)
    def wrapped(self, request, *args, **kwargs):
        user = self.request.user

        if not user.is_superuser:
            groups = [x['name'] for x in self.request.user.groups.values()]
            request_type = self.request.method
            model = str(self.model._meta).split(".")[1]
            pk = self.kwargs.get(self.pk_url_kwarg, None)

            role_groups = Role.objects.filter(group__name__in=groups).values_list('roles__table',
                                                                                  'roles__request__request',
                                                                                  'roles__permission')

            permission_dict = {}
            for i in role_groups:
                if i[0] == model and i[1] == request_type:
                    permission_dict = json.loads(i[2])

            permission_dict['id'] = pk
            obj = self.model.objects.filter(**permission_dict).count()
            if not obj:
                return HttpResponse(status=403)

        result = function(self, request, *args, **kwargs)
        return result

    return wrapped

def role_permission_update_delete(function):
    """
    //Details page control rights
    :param function:
    :return:
    """

    @wraps(function)
    def wrapped(self, request):
        user = self.request.user
        if not user.is_superuser:

            groups = [x['name'] for x in self.request.user.groups.values()]
            request_type = self.request.method
            model = str(self.model._meta).split(".")[1]
            pk = self.request.POST.get('nid', None)

            role_groups = Role.objects.filter(group__name__in=groups).values_list('roles__table',
                                                                                  'roles__request__request',
                                                                                  'roles__permission')

            permission_dict = {}
            for i in role_groups:
                if i[0] == model and i[1] == request_type:
                    permission_dict = json.loads(i[2])

            permission_dict['id'] = pk
            obj = self.model.objects.filter(**permission_dict).count()
            if not obj:
                ret = {'status': None, 'error': "No privileges,refuse", 'msg': 'Without permission, rejected'}
                return HttpResponse(json.dumps(ret))

        result = function(self, request)
        return result

    return wrapped

CBV example

  • Omit part of the code
class AssetListAll(LoginRequiredMixin, ListView):
    model = Ecs

    @role_permission_get_list
    def get_queryset(self):
        filter_dict = self.filter_dict
        self.queryset = self.model.objects.filter(**filter_dict)
        return self.queryset
class AssetChange(LoginRequiredMixin, UpdateView):
    model = Ecs

    @role_permission_detail
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    @role_permission_update_delete
    def form_valid(self, form):
        self.object = form.save()
        return super().form_valid(form)
class AssetDetail(LoginRequiredMixin, DetailView):
    model = Ecs

    @role_permission_detail
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)
class AssetDel(LoginRequiredMixin, View):
    model = Ecs

    @role_permission_update_delete
    def post(self, request):
        pass

Posted by gmann001 on Thu, 31 Jan 2019 19:03:15 -0800