重構之限制權限粒度

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>
相關文章
相關標籤/搜索