1. 程式人生 > >django 擴展自帶權限,使其支持對象權限

django 擴展自帶權限,使其支持對象權限

劃分 頁面 ural ali not in *args none 意見 verbose

擴展django 自帶權限

說明

在不重寫 自帶權限的基礎上,完成支持對象權限,適用於小型項目。
歡迎提出修改意見

軟件支持

jsonfield

數據庫

新建3個表

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=‘請求類型(大寫)‘)

    class Meta:
        db_table = "request"
        verbose_name = "請求類型"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.request

class RolePermission(models.Model):
    role = models.CharField(max_length=32, verbose_name=‘角色組‘)
    table = models.CharField(max_length=32, verbose_name=‘表名字‘)
    request = models.ManyToManyField(Request, verbose_name=‘請求‘, related_name=‘re‘, )
    permission = JSONField(max_length=1024, verbose_name=‘權限條件‘)

    class Meta:
        db_table = "role_permission"
        verbose_name = "角色組權限"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.role

class Role(models.Model):
    group = models.ForeignKey(Group, verbose_name=‘用戶組‘, on_delete=models.CASCADE)
    roles = models.ManyToManyField(RolePermission, verbose_name=‘角色組權限‘, blank=True,related_name=‘roles‘ )

    class Meta:
        db_table = "role"
        verbose_name = "角色組關系"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.group.name
system/models
Role                 角色組關系    : 系統用戶組  <-->  角色組權限
Request             請求類型      : GET ,POST
RolePermission      角色組權限    : 角色  表名字  請求  權限條件(JSON類型)

重點為 RolePermission 表。

例子

  • 以常見的資產 asset 為例

    表名字  asset     字段 groups     (分組 為 dev,ops)
  • 權限劃分
  • 新建用戶 hequan
  • 新建組 dev

  • 在Request 表 添加

    GET (代表只讀)
    POST (代表更新 刪除)

  • 在RolePermission 添加

    角色 asset-dev只讀
    表名字assset
    請求 GET
    權限條件 {"groups":‘dev‘}

  • 在Role 表中 添加

    系統用戶組 dev
    角色組權限 asset-dev只讀

權限驗證代碼

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

def role_permission_get_list(function):
    """
    列表頁面 控制權限
    :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(‘查詢條件處理後為空,默認權限‘)
                        filter_dict = permission_dict
                else:
                    print(‘查詢條件為空,默認權限‘)
                    filter_dict = permission_dict
            else:
                print(‘沒有權限‘)
                filter_dict = {‘id‘: -1}

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

    return wrapped

def role_permission_detail(function):
    """
    詳情頁面 控制權限
    :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):
    """
    詳情頁面 控制權限
    :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‘: "沒有權限,拒絕", ‘msg‘: ‘Without permission, rejected‘}
                return HttpResponse(json.dumps(ret))

        result = function(self, request)
        return result

    return wrapped

CBV 例子

  • 省略部分代碼

    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

django 擴展自帶權限,使其支持對象權限