22-1 rbac permission design

1 table structure design

 1 from django.db import models
 2 
 3 # Create your models here.
 4 from django.db import models
 5
 6 # Create your models here.
 7
 8 
 9 # User table
10 class UserInfo(models.Model):
11 username = models.CharField(max_length=16, verbose_name="username")
12 password = models.CharField(max_length=32, verbose_name="password")
13 roles = models.ManyToManyField(to="Role", null=True, blank=True)
14 # null=TRUE tells the database that this field can be empty, blank=True tells djangoadmin that it can be left blank
15
16 #Show specific content
17 def __str__(self):
18 return self.username
19
20 # Let the field display Chinese
21 class Meta:
22 verbose_name = "User table"
23 verbose_name_plural = verbose_name
twenty four 
25
26 # role
27 class Role(models.Model):
28 title = models.CharField(max_length=32, verbose_name="Character name")
29 permissions = models.ManyToManyField(to="Permission")
30
31 def __str__(self):
32 return self.title
33
34 class Meta:
35 verbose_name = "Character List"
36 verbose_name_plural = verbose_name
37
38
39 # Permission table
40 class Permission(models.Model):
41 title = models.CharField(max_length=16, verbose_name="Permission name")
42 url = models.CharField(max_length=255, verbose_name="URL")
43 is_menu = models.BooleanField(default=False, verbose_name="Can be displayed as a menu")
44 icon = models.CharField(max_length=16, verbose_name="menu icon", null=True, blank=True)
45
46 def __str__(self):
47 return self.title
48
49 class Meta:
50 verbose_name = "Permission Table"
51 verbose_name_plural = verbose_name

View Code

2. Create rbac permission management project

1. In order to achieve decoupling of the project structure, write the permission system as a separate app
1. Create APP
Steps to create an app in Django
1. Run python manage.py startapp rbac in the terminal
2. Register app in settings.py
  rbac.apps.RbacConfig
2. Execute two commands to synchronize the table structure to the database and write the statement to create the database in the models file of rbac.
1. python manage.py makemigrations
2. python manage.py migrate
3. Enter data
With Django Admin
Usage of Django admin
1. Create a super user to log in to the admin management background
python manage.py createsuperuser
2. Register the table we wrote in Django admin
Register the model in app/admin.py according to a fixed format

as follows:

 1 from django.contrib import admin
 2 from rbac import models
 3 # Registered user table
 4 admin.site.register(models.UserInfo)
 5 #Registered role table
 6 admin.site.register(models.Role)
 7
 8 
 9 # Customize a permission management class
10 class PermissionAdmin(admin.ModelAdmin):
11 # Tell django admin to display the fields of my table on the page
12 list_display = ["title","url","is_menu","icon"]
13 # You can edit the url on the list page
14 list_editable = ["url","icon","is_menu"]
15
16
17 admin.site.register(models.Permission,PermissionAdmin)

3. Permission query

It is best to encapsulate the permission query code into a separate function, so that you can directly use the rbac permission management you wrote in the future.

1 Create a new python package under the rbac directory. The name can be whatever you want, and then create a new py file. The name can be whatever you want. Here it is: permission.py

 1 from django.conf import settings
 2 
 3
 4 def init_permission(request, user_obj):
 5''
 6 Function to initialize permission information and menu information in session
 7 :param request: request object
 8:param user_obj: current logged in user
 9 :return:
10''
11
12 # user_obj.roles.all() to access all roles of the current user
13 ret = user_obj.roles.all().values("permissions__url",
14 "permissions__icon",
15 "permissions__is_menu",
16 "permissions__title"
17).distinct() # Obtain the permissions after deduplication
18 #Define a permission list
19 permission_list = []
20 #Define a list specifically used to store the current user menu
21 menu_list = []
22 for item in ret:
23 print(item) # item is a large list
24 permission_list.append({"permissions__url": item["permissions__url"]}) # Add to permission list
25 if item["permissions__is_menu"]: # if true
26 menu_list.append({
27 "title": item["permissions__title"],
28 "icon": item["permissions__icon"],
29 "url": item["permissions__url"]
30})
31
32 # Save the user permission list information into the session
33 request.session[settings.PERMISSION_SESSION_KEY] = permission_list
34 # Store all menus of the current user in sessioin
35 request.session[settings.MENU_SESSION_KEY] = menu_list

View Code

2 setting.py file configuration

# Set whitelist
PERMISSION_WHITE_URL=[
    "/login/",
    "/admin/.*",
]
#Permission list
PERMISSION_SESSION_KEY="permission_list"

#menu list
MENU_SESSION_KEY="menu_list"

Four permission verification

The permission verification function should be placed in the process_request() method in the middleware

1 Create a new python package middleware under the rbac directory, and then create an rbac.py file. The name can be whatever you want.

 1 '''
 2 Custom rbac middleware
 3''
 4 from django.utils.deprecation import MiddlewareMixin
 5 from django.shortcuts import redirect,HttpResponse,render
 6 import re
 7 from django.conf import settings
 8 
 9 class RBACMiddleware(MiddlewareMixin):
10 def process_request(self,request):
11 '''
12 Custom permission verification middleware
13 :param request: request object
14 :return:
15''
16 # 1 Get the URL accessed by the current request
17 url=request.path_info # request.get_full_path()
18 # Filter whitelist
19 for item in settings.PERMISSION_WHITE_URL:
20 reg="^{}$".format(item)
21 if re.match(reg,url):
22 return None
23 # Get the permission list of the current user
24 permission_list=request.session.get(settings.PERMISSION_SESSION_KEY,None)
25 # Perform permission verification
26 if permission_list is None:
27 # The user is not logged in
28 return redirect("/login/")
29 for i in permission_list:
30 reg="^{}$".format(i['permissions__url'])
31 if re.match(reg,url):
32 break
33 else:
34 return HttpResponse("You do not have this permission")

View Code

2 Then register it in the setting.py file

'rbac.middleware.rbac.RBACMiddleware',

5. The reference to the project login function is to import the function that just encapsulated initialization permissions.

'''
Views related to the user are written here
'''
from django.shortcuts import redirect, render, HttpResponse
from rbac.models import UserInfo
from rbac.service.permission import init_permission


def login(request):
    error_msg = ""
    if request.method == "POST":
        # Get username and password
        username = request.POST.get("username")
        pwd = request.POST.get("password")
        # verify
        user_obj = UserInfo.objects.filter(username=username, password=pwd).first()
        if user_obj:
            # login successful
            # Call the encapsulated initialization function which contains the permission list and display menu
            init_permission(request,user_obj)

            return redirect("/customer/list/")
        else:
            error_msg = "Wrong username or password"

    return render(request, "login.html")

6. Template language referenced in pages

1 First create a new python package under rbac with the name templatetags (the name must be this) and then create a new py file with any name. I call it ooxx here.

filename is to call the page you returned the result, show_menu is the name of your customized template language

from django import template

from luffy_permission import settings

register = template.Library()


@register.inclusion_tag(filename="my_menu.html")
def show_menu(request):
#menu_list is the user's menu list you get from the session
     menu_list = request.session[settings.MENU_SESSION_KEY]
    return {"menu_list": menu_list} # Return menu_list to the page my_menu.html
 

2 Create a new file my_menu.html with the same name as the filename. Create a new templates in the rbac directory.

The menu_list in this is the return result you customized above. menu.icon represents the icon field, and menu.title represents the menu name.

1 {% for menu in menu_list %}
2 <a href="{<!-- -->{ menu.url }}" class="active">
3 <span class="icon-wrap"><i class="fa {<!-- -->{ menu.icon }}"></i></span> {<!-- -->{ menu.title }}</a>
4
5 {% endfor %}

3. To allow you to reference ooxx in the HTML page that you actually show to the user, add this to the div of the menu. request is a parameter of show_menu.

 <div class="static-menu">
                {% load ooxx %}
                {% show_menu request %}

            </div>

Seven rbac permission directory structure

How to reference rbac permission management in a new project######################################## #################

1. Copy the rbac app to the project
2. Delete all migration records in the rbac/migrations directory.
3. Register the rbac app in the project
4. Create database migration (execute those two commands)

1. python manage.py makemigrations
2. python manage.py migrate

5. Register admin and enter data –> automatically discover and enter the permission URL
6. Initialize permission information during the login process, and configure the login function to reference the encapsulated initial permissions.

from django.shortcuts import render, HttpResponse, redirect
from django.conf import settings
from rbac.service.permission import init_permission
from rbac.models import UserInfo


# Create your views here.
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        pwd = request.POST.get("password")

        user_obj = UserInfo.objects.filter(username=username, password=pwd).first()
        if user_obj:
            # login successful
            #Initialize permission information
            init_permission(request, user_obj)
            return redirect("/book_list/")
    return render(request, "login.html")


def book_list(request):
    return render(request, "book_list.html")


def book_add(request):
    return render(request, "book_add.html")

View Code

7. Register middleware
8. Set permission-related configuration items in settings.py

# Set whitelist
PERMISSION_WHITE_URL=[
    "/login/",
    "/admin/.*",
]
#Permission list
PERMISSION_SESSION_KEY="permission_list"

#menu list
MENU_SESSION_KEY="menu_list"

9 Reference in html list page

 {% load ooxx %}
    {% show_menu request %}