重构之限制权限粒度

1.重新设计数据表,增加一个组字段和一个数据表
2.修改session注册
3.修改views
4.admin显示字段
5.修改中间件
6.修改user.html
7.写base.html
 
 
1.重新设计数据表,增加一个组字段和一个数据表
from django.db import models
 
# Create your models here.
 
class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    roles = models.ManyToManyField(to='Role')
 
    def __str__(self):
        return self.name
 
class Role(models.Model):
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(to='Permission')
 
    def __str__(self):
        return self.title
 
class Permission(models.Model):
    title = models.CharField(max_length=32)
    urls = models.CharField(max_length=32)
    permissiongroup = models.ForeignKey(to='PermissionGroup')
    action = models.CharField(max_length=32)
    def __str__(self):
        return self.title
 
class PermissionGroup(models.Model):
    title = models.CharField(max_length=32, default='')
    def __str__(self):
        return self.title
 
2.修改session注册
def initial_session(user, request):
    '''
    # 方案一
    ret = user.roles.all().values('permissions__urls').distinct()  # 去重
    permission_list = []
    for item in ret:  # 把queryset对象转换为列表
        permission_list.append(item['permissions__urls'])
    # 在session中注册权限列表
    request.session['permission_list'] = permission_list
    '''
 
    # 方案二
 
    permission = user.roles.all().values('permissions__urls''permissions__permissiongroup_id''permissions__action')
 
 
    permission_dict = {}
    for item in permission:
        gid = item.get('permissions__permissiongroup_id')
 
        if not gid in permission_dict:
 
            permission_dict[gid] = {
                'urls': [item.get('permissions__urls'),],
                'actions': [item.get('permissions__action'),],
            }
        else:
            permission_dict[gid]['urls'].append(item.get('permissions__urls'))
            permission_dict[gid]['actions'].append(item.get('permissions__action'))
    request.session['permission_dict'= permission_dict
 
 
'''
 
<QuerySet [
{'permissions__urls': '/user/add/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'add'}, 
{'permissions__urls': '/user/add/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'add'}, 
{'permissions__urls': '/user/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'list'}, 
{'permissions__urls': '/user/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'list'}, 
{'permissions__urls': '/user/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'list'}, 
{'permissions__urls': '/user/', 'permissions__permissiongroup_id': 1, 'permissions__action': 'list'},
{'permissions__urls': '/role/', 'permissions__permissiongroup_id': 2, 'permissions__action': 'list'}, 
{'permissions__urls': '/role/', 'permissions__permissiongroup_id': 2, 'permissions__action': 'list'}, 
{'permissions__urls': '/user/delete/(\\d+)', 'permissions__permissiongroup_id': 1, 'permissions__action': 'delete'}, 
{'permissions__urls': '/user/delete/(\\d+)', 'permissions__permissiongroup_id': 1, 'permissions__action': 'delete'}, 
{'permissions__urls': '/user/edit/(\\d+)', 'permissions__permissiongroup_id': 1, 'permissions__action': 'edit'}, 
{'permissions__urls': '/user/edit/(\\d+)', 'permissions__permissiongroup_id': 1, 'permissions__action': 'edit'}]>
 
把上面的queryset对象转化为下面的字典
 
{
  1: {
    'urls': [
        '/user/add/', '/user/add/', '/user/', '/user/', '/user/', '/user/', '/user/delete/(\\d+)', '/user/delete/(\\d+)', '/user/edit/(\\d+)', '/user/edit/(\\d+)'
        ], 
    'actions': [
        'add', 'add', 'list', 'list', 'list', 'list', 'delete', 'delete', 'edit', 'edit'
        ]},
 2: {
 'urls': ['/role/', '/role/'], 
 'actions': ['list', 'list']
}
}
'''
 
3.修改views
from django.shortcuts import render, HttpResponse
 
# Create your views here.
from rbac import models
 
 
class Per(object):
    def __init__(self, actions):
        self.actions = actions
 
    def add(self):
        return 'add' in self.actions
 
    def list(self):
        return 'list' in self.actions
 
    def edit(self):
        return 'edit' in self.actions
 
    def delete(self):
        return 'delete' in self.actions
 
 
def user(request):
    user_list = models.User.objects.all()
    # permission_list = request.session.get('permission_list')
 
    per = Per(request.actions)
    return render(request, 'user.html'locals())
 
 
import re
 
 
def user_add(request):
    permission_list = request.session[
        'permission_list']  # ['/user/add', '/user/', '/role/', '/user/delete/(\\d+)', '/user/edit/(\\d+)']
    current_path = request.path_info
 
    flag = False
 
    for permission in permission_list:
        permission = '^{}$'.format(permission)
 
        ret = re.match(permission, current_path)
        if ret:
            flag = True
            break
 
    if not flag:
        return HttpResponse('没有权限')
 
    return HttpResponse('add_user')
 
 
def user_delete(request, id):
    print('sersffdsa')
 
    return HttpResponse('delete user{}'.format(id))
 
 
def role(request):
    return HttpResponse('add_user')
 
 
from rbac.service.permission import *
 
 
def login(request):
    if request.method == 'POST':
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        user = models.User.objects.filter(name=user, password=pwd).first()
        if user:
            # 在session中注册用户id
            request.session['user_id'= user.pk
            initial_session(user, request)
            return HttpResponse('登陆成功')
    # rbac role-based access control
    return render(request, 'login.html')
 
4.admin显示字段
from django.contrib import admin
 
# Register your models here.
 
from .models import *
 
from django.contrib import admin
 
class Permissions(admin.ModelAdmin):
    list_display = ['title''urls''permissiongroup''action']
 
admin.site.register(Permission, Permissions)
 
 
admin.site.register(User)
admin.site.register(Role)
 
5.修改中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
import re
 
 
class ValidPermission(MiddlewareMixin):
 
    def process_request(self, request):
        current_path = request.path_info
        # 检查是否在白名单
        valid_url_list = ['/login/''/reg/''/admin/.*']
        for valid_url in valid_url_list:
            ret = re.match(valid_url, current_path)
            if ret:
                return None
 
        # 校验是否登陆
        user_id = request.session.get('user_id')
        if not user_id:
            return redirect('/login/')
 
 
 
        # 校验权限2
 
        permission_dict = request.session.get('permission_dict')
        # {'1': {'urls': ['/user/', '/user/delete/(\\d+)'], 'actions': ['list', 'delete']}}
        for item in permission_dict.values():
            urls = item['urls']
            for reg in urls:
                reg = '^{}$'.format(reg)
                ret = re.match(reg, current_path)
                if ret:
                    # print(item['actions'])
                    # ['list', 'delete']
                    request.actions = item['actions']
                    return None
        return HttpResponse('没有权限访问!')
 
    '''
            # 权限校验1
            permission_list = request.session[
                'permission_list']  # ['/user/add', '/user/', '/role/', '/user/delete/(\\d+)', '/user/edit/(\\d+)']
            current_path = request.path_info
 
            flag = False
            for permission in permission_list:
                permission = '^{}$'.format(permission)
                ret = re.match(permission, current_path)
                if ret:
                    flag = True
                    break
            if not flag:
                return HttpResponse('没有权限')
 
            return None
            '''
 
6.修改user.html
{% extends "base.html"%}
 
 
{% block content %}
 
    <h4>用户列表</h4>
 
    {% if per.add %}
    <a href="/user/add/" class="btn btn-primary">添加用户</a>
    {% endif %}
    <table class="table table-bordered table-striped">
        <thead>
              <tr>
                   <th>序号</th>
                   <th>姓名</th>
                   <th>角色</th>
                   <th>操作</th>
              </tr>
        </thead>
       <tbody>
            {% for user in user_list %}
            <tr>
                 <td>{{ forloop.counter }}</td>
                 <td>{{ user.name }}</td>
                 <td>
                     {% for role in user.roles.all %}
                     {{ role.title }}
                     {% endfor %}
 
                 </td>
                 <td>
                     {% if per.delete %}
                     <a href="/user/delete/{{ user.pk }}" class="btn btn-danger">删除</a>
                     {% endif %}
                        {% if per.edit %}
                         <a href="" class="btn btn-warning">编辑</a>
                        {% endif %}
 
                 </td>
            </tr>
            {% endfor %}
 
       </tbody>
    </table>
 
{% endblock %}
 
7.写base.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
        .header{
            width: 100%;
            height: 60px;
            background-color: #336699;
        }
 
        .menu{
            background-color: bisque;
            position: fixed;
            top: 60px;
            bottom: 0px;
            left: 0px;
            width: 200px;
        }
 
        .content{
            position: fixed;
            top: 60px;
            bottom: 0;
            right: 0;
            left: 200px;
            overflow: auto;
            padding: 30px;
 
        }
    </style>
</head>
<body>
 
<div class="header">
    <p>{{ user.name }}</p>
</div>
<div class="contain">
 
        <div class="menu">11</div>
        <div class="content">
        {% block content %}
 
        {% endblock %}
 
        </div>
 
</div>
 
 
</body>
</html>
 
 
 

猜你喜欢

转载自www.cnblogs.com/changwoo/p/9672002.html