Extending django's own permissions
Explain
On the basis of not rewriting its own privileges, it completes the support object privileges, which are suitable for small projects.
Amendments are welcome.
Software support
jsonfield
data base
Three new tables
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='Request type(Capital letters)') class Meta: db_table = "request" verbose_name = "Request type" verbose_name_plural = verbose_name def __str__(self): return self.request class RolePermission(models.Model): role = models.CharField(max_length=32, verbose_name='Role Groups') table = models.CharField(max_length=32, verbose_name='Table name') request = models.ManyToManyField(Request, verbose_name='request', related_name='re', ) permission = JSONField(max_length=1024, verbose_name='Privilege Conditions') class Meta: db_table = "role_permission" verbose_name = "Role group permissions" verbose_name_plural = verbose_name def __str__(self): return self.role class Role(models.Model): group = models.ForeignKey(Group, verbose_name='user group', on_delete=models.CASCADE) roles = models.ManyToManyField(RolePermission, verbose_name='Role group permissions', blank=True,related_name='roles' ) class Meta: db_table = "role" verbose_name = "Role Group Relations" verbose_name_plural = verbose_name def __str__(self): return self.group.name
system/models Role role group relationship: system user group < - > role group permissions Request request type: GET, POST RolePermission Role Group Permissions: Role Table Name Request Permission Conditions (JSON type)
The focus is on the RolePermission table.
Example
-
Take common asset asset as an example
Table name asset field groups (grouped into dev,ops)
- Delimitation of authority
- New user hequan
-
New group dev
-
Add in the Request table
GET (for read-only)
POST (for update deletion) -
Add in Role Permission
Role asset-dev read-only
Table name assset
Request GET
Permission condition {"groups":'dev'} - Add in the Role table
System User Group dev
Role group permission asset-dev read-only
Privilege Verification Code
import json from system.models import Role from functools import wraps from django.shortcuts import HttpResponse def role_permission_get_list(function): """ //List page control rights :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('Query condition is empty after processing,Default permissions') filter_dict = permission_dict else: print('Query condition is empty,Default permissions') filter_dict = permission_dict else: print('No privileges') filter_dict = {'id': -1} self.filter_dict = filter_dict result = function(self) return result return wrapped def role_permission_detail(function): """ //Details page control rights :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): """ //Details page control rights :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': "No privileges,refuse", 'msg': 'Without permission, rejected'} return HttpResponse(json.dumps(ret)) result = function(self, request) return result return wrapped
CBV example
- Omit part of the code
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