用户的管理部门权限功能
This commit is contained in:
@@ -74,6 +74,14 @@ class Users(CoreModel, AbstractUser):
|
|||||||
blank=True,
|
blank=True,
|
||||||
help_text="关联部门",
|
help_text="关联部门",
|
||||||
)
|
)
|
||||||
|
manage_dept = models.ManyToManyField(
|
||||||
|
to="Dept",
|
||||||
|
verbose_name="管理部门",
|
||||||
|
db_constraint=False,
|
||||||
|
blank=True,
|
||||||
|
help_text="管理部门",
|
||||||
|
related_name='manage_dept_set'
|
||||||
|
)
|
||||||
login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数")
|
login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数")
|
||||||
pwd_change_count = models.IntegerField(default=0,blank=True, verbose_name="密码修改次数", help_text="密码修改次数")
|
pwd_change_count = models.IntegerField(default=0,blank=True, verbose_name="密码修改次数", help_text="密码修改次数")
|
||||||
objects = CustomUserManager()
|
objects = CustomUserManager()
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ class UserCreateSerializer(CustomModelSerializer):
|
|||||||
data = super().save(**kwargs)
|
data = super().save(**kwargs)
|
||||||
data.dept_belong_id = data.dept_id
|
data.dept_belong_id = data.dept_id
|
||||||
data.save()
|
data.save()
|
||||||
|
if not self.validated_data.get('manage_dept', None):
|
||||||
|
data.manage_dept.add(data.dept_id)
|
||||||
data.post.set(self.initial_data.get("post", []))
|
data.post.set(self.initial_data.get("post", []))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@@ -127,6 +129,8 @@ class UserUpdateSerializer(CustomModelSerializer):
|
|||||||
data = super().save(**kwargs)
|
data = super().save(**kwargs)
|
||||||
data.dept_belong_id = data.dept_id
|
data.dept_belong_id = data.dept_id
|
||||||
data.save()
|
data.save()
|
||||||
|
if not self.validated_data.get('manage_dept', None):
|
||||||
|
data.manage_dept.add(data.dept_id)
|
||||||
data.post.set(self.initial_data.get("post", []))
|
data.post.set(self.initial_data.get("post", []))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@@ -426,12 +430,9 @@ class UserViewSet(CustomModelViewSet):
|
|||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
else:
|
else:
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
# print(queryset.values('id','name','dept__id'))
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
serializer = self.get_serializer(page, many=True, request=request)
|
serializer = self.get_serializer(page, many=True, request=request)
|
||||||
# print(serializer.data)
|
|
||||||
return self.get_paginated_response(serializer.data)
|
return self.get_paginated_response(serializer.data)
|
||||||
serializer = self.get_serializer(queryset, many=True, request=request)
|
serializer = self.get_serializer(queryset, many=True, request=request)
|
||||||
|
|
||||||
return SuccessResponse(data=serializer.data, msg="获取成功")
|
return SuccessResponse(data=serializer.data, msg="获取成功")
|
||||||
|
|||||||
@@ -15,15 +15,16 @@ import six
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q, F
|
from django.db.models import Q, F
|
||||||
from django.db.models.constants import LOOKUP_SEP
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
from django_filters import utils, FilterSet
|
|
||||||
from django_filters.constants import ALL_FIELDS
|
from django_filters.constants import ALL_FIELDS
|
||||||
from django_filters.filters import CharFilter, DateTimeFromToRangeFilter
|
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from django_filters.utils import get_model_field
|
from django_filters.utils import get_model_field, translate_validation, deprecate
|
||||||
|
from rest_framework.request import Request
|
||||||
from rest_framework.filters import BaseFilterBackend
|
from rest_framework.filters import BaseFilterBackend
|
||||||
from django_filters.conf import settings
|
from django_filters.conf import settings
|
||||||
from dvadmin.system.models import Dept, ApiWhiteList, RoleMenuButtonPermission, MenuButton
|
|
||||||
from dvadmin.utils.models import CoreModel
|
from dvadmin.system.models import Dept, ApiWhiteList, RoleMenuButtonPermission, MenuButton, Users
|
||||||
|
from util.currency import recursion_down_fast
|
||||||
|
|
||||||
|
|
||||||
class CoreModelFilterBankend(BaseFilterBackend):
|
class CoreModelFilterBankend(BaseFilterBackend):
|
||||||
"""
|
"""
|
||||||
@@ -200,6 +201,31 @@ class DataLevelPermissionsFilter(BaseFilterBackend):
|
|||||||
return queryset.filter(dept_belong_id__in=list(set(dept_list)))
|
return queryset.filter(dept_belong_id__in=list(set(dept_list)))
|
||||||
|
|
||||||
|
|
||||||
|
class DataLevelPermissionsSubFilter(DataLevelPermissionsFilter):
|
||||||
|
"""数据级权限过滤的子过滤器,过滤管理部门字段manage_dept"""
|
||||||
|
|
||||||
|
def _extracted_from_filter_queryset_33(self, request:Request, queryset, api, method):
|
||||||
|
u:Users = request.user
|
||||||
|
manage_depts = u.manage_dept.all()
|
||||||
|
if not manage_depts:
|
||||||
|
return queryset
|
||||||
|
dept_list = []
|
||||||
|
for dept in manage_depts:
|
||||||
|
dept_list.extend(recursion_down_fast(dept, 'parent', 'id'))
|
||||||
|
# 自己创建的数据要能看到
|
||||||
|
# 应对归属a管b、c等情况,如果自己创建数据则是a,不显式指定自己的数据就查不到
|
||||||
|
if queryset.model._meta.model_name == 'dept':
|
||||||
|
return queryset.filter(Q(id__in=set(dept_list)) | Q(creator=u))
|
||||||
|
return queryset.filter(Q(dept_belong_id__in=set(dept_list)) |
|
||||||
|
Q(creator=u))
|
||||||
|
|
||||||
|
|
||||||
|
class DataLevelPermissionMargeFilter(DataLevelPermissionsFilter):
|
||||||
|
def _extracted_from_filter_queryset_33(self, request, queryset, api, method):
|
||||||
|
queryset = super()._extracted_from_filter_queryset_33(request, queryset, api, method)
|
||||||
|
return DataLevelPermissionsSubFilter._extracted_from_filter_queryset_33(self, request, queryset, api, method)
|
||||||
|
|
||||||
|
|
||||||
class CustomDjangoFilterBackend(DjangoFilterBackend):
|
class CustomDjangoFilterBackend(DjangoFilterBackend):
|
||||||
lookup_prefixes = {
|
lookup_prefixes = {
|
||||||
"^": "istartswith",
|
"^": "istartswith",
|
||||||
@@ -240,14 +266,14 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
|
|||||||
|
|
||||||
# TODO: remove assertion in 2.1
|
# TODO: remove assertion in 2.1
|
||||||
if filterset_class is None and hasattr(view, "filter_class"):
|
if filterset_class is None and hasattr(view, "filter_class"):
|
||||||
utils.deprecate(
|
deprecate(
|
||||||
"`%s.filter_class` attribute should be renamed `filterset_class`." % view.__class__.__name__
|
"`%s.filter_class` attribute should be renamed `filterset_class`." % view.__class__.__name__
|
||||||
)
|
)
|
||||||
filterset_class = getattr(view, "filter_class", None)
|
filterset_class = getattr(view, "filter_class", None)
|
||||||
|
|
||||||
# TODO: remove assertion in 2.1
|
# TODO: remove assertion in 2.1
|
||||||
if filterset_fields is None and hasattr(view, "filter_fields"):
|
if filterset_fields is None and hasattr(view, "filter_fields"):
|
||||||
utils.deprecate(
|
deprecate(
|
||||||
"`%s.filter_fields` attribute should be renamed `filterset_fields`." % view.__class__.__name__
|
"`%s.filter_fields` attribute should be renamed `filterset_fields`." % view.__class__.__name__
|
||||||
)
|
)
|
||||||
self.filter_fields = getattr(view, "filter_fields", None)
|
self.filter_fields = getattr(view, "filter_fields", None)
|
||||||
@@ -427,5 +453,5 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
if not filterset.is_valid() and self.raise_exception:
|
if not filterset.is_valid() and self.raise_exception:
|
||||||
raise utils.translate_validation(filterset.errors)
|
raise translate_validation(filterset.errors)
|
||||||
return filterset.qs
|
return filterset.qs
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from drf_yasg.utils import swagger_auto_schema
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from dvadmin.utils.filters import DataLevelPermissionsFilter, CoreModelFilterBankend
|
from dvadmin.utils.filters import CoreModelFilterBankend, DataLevelPermissionMargeFilter
|
||||||
from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSerializerMixin
|
from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSerializerMixin
|
||||||
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse
|
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse
|
||||||
from dvadmin.utils.permission import CustomPermission
|
from dvadmin.utils.permission import CustomPermission
|
||||||
@@ -41,7 +41,7 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi
|
|||||||
update_serializer_class = None
|
update_serializer_class = None
|
||||||
filter_fields = '__all__'
|
filter_fields = '__all__'
|
||||||
search_fields = ()
|
search_fields = ()
|
||||||
extra_filter_class = [CoreModelFilterBankend,DataLevelPermissionsFilter]
|
extra_filter_class = [CoreModelFilterBankend,DataLevelPermissionMargeFilter]
|
||||||
permission_classes = [CustomPermission]
|
permission_classes = [CustomPermission]
|
||||||
import_field_dict = {}
|
import_field_dict = {}
|
||||||
export_field_label = {}
|
export_field_label = {}
|
||||||
|
|||||||
@@ -205,10 +205,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
dept: {
|
dept: {
|
||||||
title: '部门',
|
title: '所属部门',
|
||||||
search: {
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
type: 'dict-tree',
|
type: 'dict-tree',
|
||||||
dict: dict({
|
dict: dict({
|
||||||
isTree: true,
|
isTree: true,
|
||||||
@@ -217,7 +214,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
|
|||||||
label: 'name'
|
label: 'name'
|
||||||
}),
|
}),
|
||||||
column: {
|
column: {
|
||||||
minWidth: 200, //最小列宽
|
minWidth: 300, //最小列宽
|
||||||
formatter({ value, row, index }) {
|
formatter({ value, row, index }) {
|
||||||
return row.dept_name_all
|
return row.dept_name_all
|
||||||
}
|
}
|
||||||
@@ -243,6 +240,39 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
manage_dept: {
|
||||||
|
title: '管理部门',
|
||||||
|
type: 'dict-tree',
|
||||||
|
dict: dict({
|
||||||
|
isTree: true,
|
||||||
|
url: '/api/system/dept/all_dept/',
|
||||||
|
value: 'id',
|
||||||
|
label: 'name'
|
||||||
|
}),
|
||||||
|
column: {
|
||||||
|
minWidth: 300
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
value: [],
|
||||||
|
component: {
|
||||||
|
filterable: true,
|
||||||
|
multiple: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
clearable: true,
|
||||||
|
collapseTags: true,
|
||||||
|
maxCollapseTags: 2,
|
||||||
|
collapseTagsTooltip: true,
|
||||||
|
props: {
|
||||||
|
checkStrictly: true,
|
||||||
|
props: {
|
||||||
|
value: 'id',
|
||||||
|
label: 'name',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
helper: '不选则默认为所属部门',
|
||||||
|
},
|
||||||
|
},
|
||||||
role: {
|
role: {
|
||||||
title: '角色',
|
title: '角色',
|
||||||
search: {
|
search: {
|
||||||
@@ -378,6 +408,9 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
|
|||||||
dict: dict({
|
dict: dict({
|
||||||
data: dictionary('button_status_bool'),
|
data: dictionary('button_status_bool'),
|
||||||
}),
|
}),
|
||||||
|
form: {
|
||||||
|
value: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
title: '头像',
|
title: '头像',
|
||||||
@@ -392,8 +425,8 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
|
|||||||
},
|
},
|
||||||
...commonCrudConfig({
|
...commonCrudConfig({
|
||||||
dept_belong_id: {
|
dept_belong_id: {
|
||||||
form: true,
|
form: false,
|
||||||
table: true
|
table: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user