首页 > 其他分享 >三十三、RBAC+动态菜单

三十三、RBAC+动态菜单

时间:2024-02-12 23:44:06浏览次数:28  
标签:__ 菜单 三十三 models menu self list RBAC dict

role base access control 基于角色的权限控制

1、Models

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = '用户表'

    def __str__(self):
        return self.name

class Role(models.Model):
    caption = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = '角色表'

    def __str__(self):
        return self.caption

class User2Role(models.Model):
    u = models.ForeignKey(User, on_delete=models.CASCADE)
    r = models.ForeignKey(Role, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = '用户角色表'
        unique_together = [
            ('u', 'r'),
        ]

    def __str__(self):
        return '%s-%s'%(self.u,self.r)

class Permission(models.Model):
    caption = models.CharField(max_length=32, unique=True)
    url = models.CharField(max_length=128, unique=True)
    menu = models.ForeignKey('Menu', on_delete=models.CASCADE, blank=True, null=True)

    class Meta:
        verbose_name_plural = 'url表'
        unique_together = [
            ('caption','url'),
        ]

    def __str__(self):
        return self.caption + self.url

class Action(models.Model):
    caption = models.CharField(max_length=32)
    code = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = '动作表'

    def __str__(self):
        return self.caption + ":" + self.code

class Permission2Action(models.Model):
    p = models.ForeignKey(Permission, on_delete=models.CASCADE)
    a = models.ForeignKey(Action, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = '权限表'
        unique_together = [
            ('p','a'),
        ]

    def __str__(self):
        return '%s-%s:%s-%s'%(self.p.caption, self.a.caption, self.p.url, self.a.code)

class Permission2Action2Role(models.Model):
    p2a = models.ForeignKey(Permission2Action, on_delete=models.CASCADE)
    r = models.ForeignKey(Role, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = '角色权限表'
        unique_together = [
            ('p2a', 'r'),
        ]

    def __str__(self):
        return '%s:%s'%(self.r.caption, self.p2a)

class Menu(models.Model):
    caption = models.CharField(max_length=32)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True,null=True)

    class Meta:
        verbose_name_plural = '菜单表'

    def __str__(self):
        return self.caption

2、权限、菜单

class MenuHelper():
    def __init__(self, request, username):
        self.permission2action_dict = None
        self.menu_leaf_list = None
        self.menu_list = None
        self.__menu_str = None
        self.username = username
        self.current_url = request.path_info
        self.request = request
        self.session_data()

    def session_data(self):
        # 获取当前用户的所有权限
        # 获取在菜单中显示的权限
        # 获取所有菜单
        # 放置session中
        info_session_key = 'permission_info'
        permission2action_dict_key = 'permission2action_dict'
        menu_leaf_list_key = 'menu_leaf_list'
        menu_list_key = 'menu_list'
        permission_dict = self.request.session.get(info_session_key)
        if permission_dict:
            self.permission2action_dict = permission_dict[permission2action_dict_key]
            self.menu_leaf_list = permission_dict[menu_leaf_list_key]
            self.menu_list = permission_dict[menu_list_key]
        else:
            roles = models.Role.objects.filter(user2role__u__name=self.username).all()
            # p = models.Permission2Action2Role.objects.filter(r__in=role).values('p2a')
            permission2action = models.Permission2Action.objects. \
                filter(permission2action2role__r__in=roles). \
                distinct().values('p__url', 'a__code')
            permission2action_dict = {}
            for pa in permission2action:
                url = pa['p__url']
                code = pa['a__code']
                if url in permission2action_dict:
                    permission2action_dict[url].append(code)
                else:
                    permission2action_dict[url] = [code, ]

            menu_leaf_list = list(models.Permission2Action.objects.filter(permission2action2role__r__in=roles). \
                                  exclude(p__menu__isnull=True). \
                                  distinct().values('p__id', 'p__caption', 'p__url', 'p__menu'))
            menus = list(models.Menu.objects.values('id', 'caption', 'parent_id'))
            self.request.session[info_session_key] = {
                permission2action_dict_key: permission2action_dict,
                menu_leaf_list_key: menu_leaf_list,
                menu_list_key: menus,
            }
            self.permission2action_dict = permission2action_dict
            self.menu_leaf_list = menu_leaf_list
            self.menu_list = menus

    def menu_data_list(self):
        url_parent_id = None
        m2_dict = {}
        for i in self.menu_leaf_list:
            item = {
                'caption': i['p__caption'],
                'url': i['p__url'],
                'parent_id': i['p__menu'],
                'child': [],
                'status': True,
                'open': False,
            }
            key = item['parent_id']
            if key in m2_dict:
                m2_dict[key].append(item)
            else:
                m2_dict[key] = [item, ]
            if re.match(item['url'], self.current_url):
                url_parent_id = item['parent_id']
                item['open'] = True

        menu_dict = {}
        for menu in self.menu_list:
            menu['child'] = []
            menu['status'] = False
            menu['open'] = False
            menu_dict[menu['id']] = menu

        for k, v in m2_dict.items():
            menu_dict[k]['child'] = v
            parent_id = k
            while parent_id:
                menu_dict[parent_id]['status'] = True
                parent_id = menu_dict[parent_id]['parent_id']

        menus = []
        for k, v in menu_dict.items():
            key = v['parent_id']
            if key:
                menu_dict[key]['child'].append(v)
            else:
                menus.append(v)
        while url_parent_id:
            menu_dict[url_parent_id]['open'] = True
            url_parent_id = menu_dict[url_parent_id]['parent_id']
        return menus

    def menu_str(self):
        if self.__menu_str: return self.__menu_str
        menus = self.menu_data_list()
        if menus.count:
            s = ''
            for m in menus:
                if not m['status']: continue
                s2 = self.__menu_content_str(m['child'])
                if s2:
                    s += '<li><a href="javaScript:void(0);">%s</a>%s</li>' % (m['caption'], s2)
                elif m['url']:
                    s += '<li><a href="%s">%s</a></li>' % (m['url'], m['caption'])
                else:
                    s += '<li>%s</li>' % m['caption']
            self.__menu_str = '<ul class="active">%s</ul>' % s if s else None
            return self.__menu_str
        else:
            return None
    def __menu_content_str(self, menus):
        if menus.count:
            s = ''
            active = ''
            for m in menus:
                if not m['status']: continue
                s2 = self.__menu_content_str(m['child'])
                if s2:
                    s += '<li><a href="javaScript:void(0);">%s</a>%s</li>' % (m['caption'], s2)
                elif m['url']:
                    s += '<li><a href="%s">%s</a></li>' % (m['url'], m['caption'])
                else:
                    s += '<li>%s</li>' % m['caption']
                if m['open']:
                    active = 'active'
            return '<ul class="%s">%s</ul>' % (active, s) if s else None
        else:
            return None

    def actions(self):
        """
        检查当前用户是否对当前URL有权访问,并获取对当前URL有什么权限
        """
        action_list = []
        # 当前所有权限
        # {
        #     '/index.html': ['GET',POST,]
        # }
        for k,v in self.permission2action_dict.items():
            if re.match(k,self.current_url):
                action_list = v # ['GET',POST,]
                break
        return action_list

3、权限控制装饰器

def permission(func):
    def inner(request,*args,**kwargs):
        user_info = request.session.get('user_info')
        if not user_info:
            return redirect(reverse('login'))
        obj = MenuHelper(request, user_info['username'])
        action_list = obj.actions()
        if not action_list:
            return HttpResponse('无权限访问')
        kwargs['menu_string'] = obj.menu_str()
        kwargs['action_list'] = action_list
        return func(request,*args,**kwargs)
    return inner

4、应用

 <div class="menu">
     {{ menu_str|safe }}  # 菜单元素
 </div>
def login(request):
    if request.method == "GET":
        return render(request,'login.html')
    else:
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        obj = models.User.objects.filter(name=username,password=pwd).first()
        if obj:
            # obj.id,  obj.username
            # 当前用户信息放置session中
            request.session['user_info'] = {'nid':obj.id,'username':obj.name}
            MenuHelper(request,obj.name)
            return redirect('/')
        else:
            return redirect('/login/')

def logout(request):
    request.session.clear()
    return redirect('/login/')

@permission
def index(request,*args,**kwargs):
    action_list = kwargs.get('action_list')
    menu_string = kwargs.get('menu_string')
    if "GET" in action_list:
        result = models.User.objects.all()
    else:
        result = []
    return render(request,'index.html',{'menu_string':menu_string,'action_list':action_list})

标签:__,菜单,三十三,models,menu,self,list,RBAC,dict
From: https://www.cnblogs.com/zhlforhe/p/18014266

相关文章

  • Vue3学习(16) - 左侧显示分类菜单
    写在前面和大家不太一样,我觉得今年的自己更加relax,没有亲戚要走,没有朋友相聚,也没有很好的哥们要去叙旧,更没有无知的相亲,甚至可以这么说没有那些闲得慌的邻居。也可以说是从今天开始,算是可以进入自己的小世界,做自己想做的事,看看书,学习一下。生活的精髓在于善待自己,用心感受每一......
  • vue2中el-tree组件实现右键菜单功能
    目标右键点击树组件中的节点,弹出增删改的菜单,要求菜单总是在点击位置的附近先添加一个树<template><div><el-tree<!--绑定数据-->:data="tree"highlight-currentnode-key="id":props=&quo......
  • [office] excel2003创建下拉菜单的方法
    Excel中的下拉菜单具体该如何创建呢?下面是由小编分享的excel2003创建下拉菜单的方法,以供大家阅读和学习。excel2003创建下拉菜单的方法:创建下拉菜单步骤1:首先选择要生成下拉菜单的单元格创建下拉菜单步骤2:点击菜单[数据]->[有效性]创建下拉菜单步骤3:在允许项......
  • 年夜饭都吃什么菜寓意吉祥?年夜饭菜单快记到待办清单
    春节将至,一顿令人期待的盛宴——年夜饭,将成为万家团圆的美好时刻。这顿丰盛的晚餐不仅是年夜饭,更是亲情的独特味道。那么在这个重要的时刻,年夜饭都吃什么菜寓意吉祥呢?其实,寓意吉祥的年夜饭菜单有很多,比如清蒸鲈鱼代表年年有余,红烧肉寓意红红火火,可乐鸡翅象征展翅高飞,糖醋排骨寓意......
  • (12)动态生成菜单及绑定自定义事件
    varAddCollctMenus:ArrayOfTMenuItem;//动态菜单 procedureTForm1.Button5Click(Sender:TObject);Vari,AddCollctMenuCount:Integer;BeginAddCollctMenuCount:=Length(AddCollctMenus)-1;Fori:=0ToAddCollctMenuCountDoBeginFreeAndNil......
  • (12)动态生成菜单及绑定自定义事件
    varAddCollctMenus:ArrayOfTMenuItem;//动态菜单      procedureTForm1.Button5Click(Sender:TObject);Vari,AddCollctMenuCount:Integer;BeginAddCollctMenuCount:=Length(AddCollctMenus)-1;Fori:=0ToAddCollctMenuCountDo......
  • Kubernetes 为用户使用 Dashboard 创建 RBAC 权限
    文章目录目录文章目录一、创建Namespace二、创建ServiceAccount三、创建Namespace的RBAC权限1、方式一:使用系统提供角色分配Namespace权限2、方式二:使用自定义角色分配Namespace权限四、解决登录Dashboard不能选择Namespace问题系统环境:kubernetes版本:1.16.3......
  • vue项目路由配置,打开页面空白,其他菜单正常显示问题
     如果你的项目文件夹里面的内容同时存在index.js  index.vue(类似),那么路由配置路径的时候一定要带上.vue如果单纯的写Index,会找到.js文件,导致页面不显示   ......
  • NanoFramework操作ESP32(一)_基础元器件篇(三十三)_ KY-020倾斜开关
    一、元器件介绍  KY-020倾斜开关模块由一个10kΩ电阻器和一个具有双向导电性的金属球开关组成,该开关根据倾斜程度来打开/关闭电路。它不测量倾斜角。当电路向侧面倾斜时,只要以足够的力和倾斜度移动电路,即可激活内部的球开关,从而使电路闭合。以输出低电平电压信号。可使用数字......
  • notepad怎么保存utf-8格式 菜单栏"编码”下拉菜单中选择“UTF-8” 或者Encoding选择 U
    notepad怎么保存utf-8格式菜单栏"编码”下拉菜单中选择“UTF-8”或者Encoding选择UTF-8,或者菜单栏-格式->以UTF-8无BOM格式编码要在Notepad中保存UTF-8格式,可以按照以下步骤操作:1.打开Notepad,然后新建一个文本文档。2.将要保存为UTF-8格式的文本复制粘贴到Notepad中。3.点......