!11 修复多个bug
* 修复BUG(中间件bug): 日志中间件存入模块信息不全 * 测试(部署测试): * 修复BUG(文件上传): doc,docx,xlsx文件都无法上传成功 * 修复BUG(删除部门): 部门里面存在用户,依然能够删除部门pull/11/MERGE
parent
ab6c4731d4
commit
ef8a365ec0
|
@ -54,7 +54,6 @@ INSTALLED_APPS = [
|
|||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'vadmin.op_drf.middleware.PermissionModeMiddleware', # 权限中间件
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
|
@ -64,6 +63,7 @@ MIDDLEWARE = [
|
|||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'vadmin.op_drf.middleware.ApiLoggingMiddleware', # 用于记录API访问日志
|
||||
'vadmin.op_drf.middleware.PermissionModeMiddleware', # 权限中间件
|
||||
]
|
||||
# 允许跨域源
|
||||
CORS_ORIGIN_ALLOW_ALL = CORS_ORIGIN_ALLOW_ALL
|
||||
|
|
|
@ -18,13 +18,6 @@ class ViewLogger(object):
|
|||
self.request = request
|
||||
self.model = None
|
||||
self.log_prefix: str = ''
|
||||
if self.view and hasattr(self.view.get_queryset(), 'model'):
|
||||
self.model: Model = self.view.get_queryset().model
|
||||
elif self.view and hasattr(self.view.get_serializer(), 'Meta') and hasattr(self.view.get_serializer().Meta,
|
||||
'model'):
|
||||
self.model: Model = self.view.get_serializer().Meta.model
|
||||
if self.model:
|
||||
request.session['model_name'] = str(getattr(self.model, '_meta').verbose_name)
|
||||
|
||||
def handle(self, request: Request, *args, **kwargs):
|
||||
pass
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
django中间件
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
@ -11,7 +12,7 @@ from django.utils.deprecation import MiddlewareMixin
|
|||
from apps.vadmin.permission.models import Menu
|
||||
from apps.vadmin.system.models import OperationLog
|
||||
from ..utils.request_util import get_request_ip, get_request_data, get_request_path, get_browser, get_os, \
|
||||
get_login_location, get_request_canonical_path, get_request_user
|
||||
get_login_location, get_request_canonical_path, get_request_user, get_verbose_name
|
||||
from ..utils.response import ErrorJsonResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -42,9 +43,16 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
|||
body['password'] = '*' * len(body['password'])
|
||||
if not hasattr(response, 'data') or not isinstance(response.data, dict):
|
||||
response.data = {}
|
||||
if not response.data and response.content:
|
||||
try:
|
||||
content = json.loads(response.content.decode())
|
||||
response.data = content if isinstance(content, dict) else {}
|
||||
except:
|
||||
pass
|
||||
user = get_request_user(request)
|
||||
info = {
|
||||
'request_ip': getattr(request, 'request_ip', 'unknown'),
|
||||
'creator': request.user,
|
||||
'creator': user if not isinstance(user, AnonymousUser) else '',
|
||||
'dept_belong_id': getattr(request.user, 'dept_id', None),
|
||||
'request_method': request.method,
|
||||
'request_path': request.request_path,
|
||||
|
@ -58,11 +66,14 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
|||
'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
|
||||
'request_modular': request.session.get('model_name'),
|
||||
}
|
||||
if isinstance(request.user, AnonymousUser):
|
||||
info['creator'] = None
|
||||
log = OperationLog(**info)
|
||||
log.save()
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
if view_func.cls and hasattr(view_func.cls, 'queryset'):
|
||||
request.session['model_name'] = get_verbose_name(view_func.cls.queryset)
|
||||
return
|
||||
|
||||
def process_request(self, request):
|
||||
self.__handle_request(request)
|
||||
|
||||
|
@ -85,14 +96,7 @@ class PermissionModeMiddleware(MiddlewareMixin):
|
|||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
"""
|
||||
判断环境变量中,是否为演示模式(正常可忽略此判断)
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
white_list = ['/admin/logout/', '/admin/login/']
|
||||
if os.getenv('DEMO_ENV') and not request.method == 'GET' and request.path not in white_list:
|
||||
return ErrorJsonResponse(data={}, msg=f'演示模式,不允许操作!')
|
||||
return
|
||||
|
||||
def has_interface_permission(self, request, method, view_path, user=None):
|
||||
"""
|
||||
|
@ -135,13 +139,18 @@ class PermissionModeMiddleware(MiddlewareMixin):
|
|||
return -10
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
# 判断环境变量中,是否为演示模式(正常可忽略此判断)
|
||||
white_list = ['/admin/logout/', '/admin/login/']
|
||||
if not os.getenv('DEMO_ENV') and not request.method in ['GET', 'OPTIONS'] and request.path not in white_list:
|
||||
return ErrorJsonResponse(data={}, msg=f'演示模式,不允许操作!')
|
||||
|
||||
if not settings.INTERFACE_PERMISSION:
|
||||
return
|
||||
user = get_request_user(request)
|
||||
|
||||
if user and not isinstance(user, AnonymousUser):
|
||||
method = request.method.upper()
|
||||
if method == 'GET': # GET 不设置接口权限
|
||||
if method == 'GET': # GET 不设置接口权限
|
||||
return
|
||||
view_path = get_request_canonical_path(request, *view_args, **view_kwargs)
|
||||
auth_code = self.has_interface_permission(request, method, view_path, user)
|
||||
|
|
|
@ -93,3 +93,23 @@ class CommonPermission(CustomPermission):
|
|||
self.message = f"没有此数据操作权限!"
|
||||
res = self.check_queryset(request, instance)
|
||||
return res
|
||||
|
||||
|
||||
class DeptDestroyPermission(CustomPermission):
|
||||
"""
|
||||
部门删除权限校验:判断部门下是否有用户存在,存在不可删除
|
||||
"""
|
||||
message = '没有有操作权限'
|
||||
|
||||
def has_permission(self, request: Request, view: APIView):
|
||||
return True
|
||||
|
||||
def check_queryset(self, request, instance):
|
||||
if instance.values_list('userprofile', flat=True):
|
||||
self.message = "该部门下有关联用户,无法删除!"
|
||||
return False
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, instance):
|
||||
res = self.check_queryset(request, instance)
|
||||
return res
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib.auth import authenticate
|
|||
from rest_framework.request import Request
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from .permissions import CommonPermission
|
||||
from .permissions import CommonPermission, DeptDestroyPermission
|
||||
from ..op_drf.filters import DataLevelPermissionsFilter
|
||||
from ..op_drf.viewsets import CustomModelViewSet
|
||||
from ..permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter
|
||||
|
@ -129,7 +129,7 @@ class DeptModelViewSet(CustomModelViewSet):
|
|||
filter_class = DeptFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission, DeptDestroyPermission)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('deptName',)
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
|
|
|
@ -13,7 +13,7 @@ def files_path(instance, filename):
|
|||
|
||||
class SaveFile(CoreModel):
|
||||
name = CharField(max_length=128, verbose_name="文件名称", null=True, blank=True)
|
||||
type = CharField(max_length=32, verbose_name="文件类型", null=True, blank=True)
|
||||
type = CharField(max_length=200, verbose_name="文件类型", null=True, blank=True)
|
||||
size = CharField(max_length=64, verbose_name="文件大小", null=True, blank=True)
|
||||
address = CharField(max_length=16, verbose_name="存储位置", null=True, blank=True) # 本地、阿里云、腾讯云..
|
||||
source = CharField(max_length=16, verbose_name="文件来源", null=True, blank=True) # 导出、用户上传.
|
||||
|
|
|
@ -65,8 +65,6 @@ def op_exception_handler(ex, context):
|
|||
"""
|
||||
msg = ''
|
||||
code = '201'
|
||||
request = context.get('request')
|
||||
request.session['model_name'] = str(get_verbose_name(view=context.get('view')))
|
||||
|
||||
if isinstance(ex, AuthenticationFailed):
|
||||
code = 401
|
||||
|
|
Loading…
Reference in New Issue