diff --git a/apps/system/apps.py b/apps/system/apps.py index 59d27b05..bf6e73d0 100755 --- a/apps/system/apps.py +++ b/apps/system/apps.py @@ -12,4 +12,10 @@ class SystemConfig(AppConfig): from server.settings import get_sysconfig get_sysconfig(reload=True) cache.set('cache_sysconfig_need_task', False, timeout=30) + + if cache.get('cache_alldperms_task', True): + from apps.utils.permission import get_alld_perms + get_alld_perms(update_cache=True) + cache.set('cache_alldperms_task', False, timeout=30) + return super().ready() diff --git a/apps/system/views.py b/apps/system/views.py index 7fb0cd70..c14b26c1 100755 --- a/apps/system/views.py +++ b/apps/system/views.py @@ -24,7 +24,7 @@ from apps.system.filters import DeptFilterSet, UserFilterSet # from django_q.models import Task as QTask, Schedule as QSchedule from apps.utils.mixins import (CustomCreateModelMixin, MyLoggingMixin) from django.conf import settings -from apps.utils.permission import ALL_PERMS, get_user_perms_map +from apps.utils.permission import ALL_PERMS, get_user_perms_map, get_alld_perms from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from server.celery import app as celery_app from .models import (Dept, Dictionary, DictType, File, Permission, Post, PostRole, Role, User, @@ -44,6 +44,7 @@ import locale from drf_yasg.utils import swagger_auto_schema from server.settings import get_sysconfig, update_sysconfig, update_dict from apps.utils.constants import DEFAULT_PWD +from apps.utils.thread import MyThread # logger.info('请求成功! response_code:{};response_headers:{}; # response_body:{}'.format(response_code, response_headers, response_body[:251])) @@ -317,7 +318,18 @@ class PermissionViewSet(CustomModelViewSet): """ ALL_PERMS.sort() return Response(ALL_PERMS) - + + def perform_create(self, serializer): + super().perform_create(serializer) + MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() + + def perform_update(self, serializer): + super().perform_update(serializer) + MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() + + def perform_destroy(self, instance): + super().perform_destroy(instance) + MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() class DeptViewSet(CustomModelViewSet): """部门-增删改查 @@ -531,7 +543,7 @@ class UserViewSet(CustomModelViewSet): 获取登录用户信息 """ user = request.user - perms = get_user_perms_map(user) + perms = get_user_perms_map(user, update_cache=True) data = { 'id': user.id, 'username': user.username, diff --git a/apps/utils/permission.py b/apps/utils/permission.py index aaa07f29..0506ebad 100755 --- a/apps/utils/permission.py +++ b/apps/utils/permission.py @@ -5,40 +5,52 @@ from apps.system.models import DataFilter, Dept, Permission, PostRole, UserPost, from django.db.models.query import QuerySet from typing import List +# 后端代码里有的权限标识 ALL_PERMS = [ ] +# 数据库里定义的权限标识 +def get_alld_perms(update_cache=False) -> List[str]: + key = "perms_alld_list" + perms_alld_list = cache.get(key) + if perms_alld_list is None or update_cache: + nested_list = Permission.objects.all().values_list('codes', flat=True) + perms_alld_list = list(set([item for sublist in nested_list for item in sublist])) + perms_alld_list.sort() + cache.set(key, perms_alld_list, timeout=60*5) + return perms_alld_list -def get_user_perms_map(user): +def get_user_perms_map(user, update_cache=False): """ 获取权限字典,可用redis存取(包括功能和数据权限) """ - user_perms_map = {} - if user.is_superuser: - for perm in Permission.objects.all(): - if perm.codes: - for code in perm.codes: - user_perms_map[code] = {} - else: - objs = UserPost.objects.filter(user=user).exclude(post=None) - for i in objs: - dept_id = str(i.dept.id) - for pr in PostRole.objects.filter(post=i.post): - """ - 岗位角色 - """ - for perm in Permission.objects.filter(role_perms=pr.role): - if perm.codes: - for code in perm.codes: - if code in user_perms_map: - data_range = user_perms_map[code].get( - dept_id, -1) - if pr.data_range < data_range: - user_perms_map[code][dept_id] = pr.data_range - else: - user_perms_map[code] = {dept_id: pr.data_range} - cache.set('perms_' + str(user.id), user_perms_map, timeout=300) + key = f'perms_{str(user.id)}' + if cache.get(key) is None or update_cache: + user_perms_map = {} + if user.is_superuser: + codes = get_alld_perms() + for code in codes: + user_perms_map[code] = {} + else: + objs = UserPost.objects.filter(user=user).exclude(post=None) + for i in objs: + dept_id = str(i.dept.id) + for pr in PostRole.objects.filter(post=i.post): + """ + 岗位角色 + """ + for perm in Permission.objects.filter(role_perms=pr.role): + if perm.codes: + for code in perm.codes: + if code in user_perms_map: + data_range = user_perms_map[code].get( + dept_id, -1) + if pr.data_range < data_range: + user_perms_map[code][dept_id] = pr.data_range + else: + user_perms_map[code] = {dept_id: pr.data_range} + cache.set(key, user_perms_map, timeout=300) return user_perms_map diff --git a/apps/utils/thread.py b/apps/utils/thread.py index 5276955e..419dbcea 100644 --- a/apps/utils/thread.py +++ b/apps/utils/thread.py @@ -1,9 +1,17 @@ import threading from apps.utils.decorators import auto_log +from concurrent.futures import ThreadPoolExecutor +# 创建全局线程池 +global_executor = ThreadPoolExecutor(max_workers=20) class MyThread(threading.Thread): @auto_log('MyThread', raise_exception=True, send_mail=True) def run(self) -> None: return super().run() - \ No newline at end of file + + def start_p(self): + """ + 使用线程池启动 + """ + global_executor.submit(self.run) \ No newline at end of file diff --git a/apps/utils/viewsets.py b/apps/utils/viewsets.py index db865a2c..0d816a0a 100755 --- a/apps/utils/viewsets.py +++ b/apps/utils/viewsets.py @@ -21,6 +21,7 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): """ 增强的GenericViewSet """ + _initialized = False perms_map = None # 权限标识 throttle_classes = [UserRateThrottle] logging_methods = ['POST', 'PUT', 'PATCH', 'DELETE'] @@ -44,13 +45,15 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): """ 第一次实例化时,将权限标识添加到全局权限标识列表中 """ - if cls.perms_map is None: - basename = kwargs["basename"] - cls.perms_map = {'get': '*', 'post': '{}.create'.format(basename), 'put': '{}.update'.format( - basename), 'patch': '{}.update'.format(basename), 'delete': '{}.delete'.format(basename)} - for _, v in cls.perms_map.items(): - if v not in ALL_PERMS and v != '*': - ALL_PERMS.append(v) + if not cls._initialized: + if cls.perms_map is None: + basename = kwargs["basename"] + cls.perms_map = {'get': '*', 'post': '{}.create'.format(basename), 'put': '{}.update'.format( + basename), 'patch': '{}.update'.format(basename), 'delete': '{}.delete'.format(basename)} + for _, v in cls.perms_map.items(): + if v not in ALL_PERMS and v != '*': + ALL_PERMS.append(v) + cls._initialized = True return super().__new__(cls) def finalize_response(self, request, response, *args, **kwargs): @@ -87,15 +90,6 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): return action_serializer_class return super().get_serializer_class() - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - if self.perms_map: - for k, v in self.perms_map.items(): - if v not in ALL_PERMS and v != '*': - ALL_PERMS.append(v) - if not hasattr(self, 'filterset_fields'): - self.filterset_fields = self.select_related_fields - def get_queryset_custom(self, queryset): """ 自定义过滤方法可复写