diff --git a/backend/application/routing.py b/backend/application/routing.py index 237e5d1..d4df9f8 100644 --- a/backend/application/routing.py +++ b/backend/application/routing.py @@ -3,6 +3,5 @@ from django.urls import path from application.websocketConfig import MegCenter websocket_urlpatterns = [ - path('ws//', MegCenter.as_asgi()), #consumers.DvadminWebSocket 是该路由的消费者 + path('ws//', MegCenter.as_asgi()), # consumers.DvadminWebSocket 是该路由的消费者 ] - diff --git a/backend/application/settings.py b/backend/application/settings.py index f2cca95..b311bae 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -166,9 +166,9 @@ CORS_ORIGIN_ALLOW_ALL = True # 允许cookie CORS_ALLOW_CREDENTIALS = True # 指明在跨域访问中,后端是否支持对cookie的操作 -# ================================================= # +# ===================================================== # # ********************* channels配置 ******************* # -# ================================================= # +# ===================================================== # ASGI_APPLICATION = 'application.asgi.application' CHANNEL_LAYERS = { "default": { @@ -306,7 +306,7 @@ AUTHENTICATION_BACKENDS = ["dvadmin.utils.backends.CustomBackend"] # ================================================= # SIMPLE_JWT = { # token有效时长 - "ACCESS_TOKEN_LIFETIME": timedelta(minutes=120), + "ACCESS_TOKEN_LIFETIME": timedelta(minutes=1440), # token刷新后的有效时间 "REFRESH_TOKEN_LIFETIME": timedelta(days=1), # 设置前缀 diff --git a/backend/application/urls.py b/backend/application/urls.py index f7ba7cb..6648052 100644 --- a/backend/application/urls.py +++ b/backend/application/urls.py @@ -30,6 +30,7 @@ from dvadmin.system.views.login import ( CaptchaView, ApiLogin, LogoutView, + LoginTokenView ) from dvadmin.system.views.system_config import InitSettingsViewSet from dvadmin.utils.swagger import CustomOpenAPISchemaGenerator @@ -81,6 +82,9 @@ urlpatterns = ( path("api/init/dictionary/", InitDictionaryViewSet.as_view()), path("api/init/settings/", InitSettingsViewSet.as_view()), path("apiLogin/", ApiLogin.as_view()), + + # 仅用于开发,上线需关闭 + path("api/token/", LoginTokenView.as_view()), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_URL) diff --git a/backend/application/websocketConfig.py b/backend/application/websocketConfig.py index 80515f4..c36d97a 100644 --- a/backend/application/websocketConfig.py +++ b/backend/application/websocketConfig.py @@ -122,7 +122,8 @@ class MessageCreateSerializer(CustomModelSerializer): fields = "__all__" read_only_fields = ["id"] -def websocket_push(user_id,message): + +def websocket_push(user_id, message): username = "user_" + str(user_id) channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( @@ -133,8 +134,9 @@ def websocket_push(user_id,message): } ) -def create_message_push(title: str, content: str, target_type: int=0, target_user: list=[], target_dept=None, target_role=None, - message: dict = {'contentType': 'INFO', 'content': '测试~'}, request= Request): + +def create_message_push(title: str, content: str, target_type: int = 0, target_user: list = None, target_dept=None, + target_role=None, message: dict = None, request=Request): if message is None: message = {"contentType": "INFO", "content": None} if target_role is None: @@ -145,11 +147,11 @@ def create_message_push(title: str, content: str, target_type: int=0, target_use "title": title, "content": content, "target_type": target_type, - "target_user":target_user, - "target_dept":target_dept, - "target_role":target_role + "target_user": target_user, + "target_dept": target_dept, + "target_role": target_role } - message_center_instance = MessageCreateSerializer(data=data,request=request) + message_center_instance = MessageCreateSerializer(data=data, request=request) message_center_instance.is_valid(raise_exception=True) message_center_instance.save() users = target_user or [] @@ -176,6 +178,6 @@ def create_message_push(title: str, content: str, target_type: int=0, target_use username, { "type": "push.message", - "json": {**message,'unread':unread_count} + "json": {**message, 'unread': unread_count} } ) diff --git a/backend/dvadmin/system/fixtures/init_menu.json b/backend/dvadmin/system/fixtures/init_menu.json index 14f6520..9d514fe 100644 --- a/backend/dvadmin/system/fixtures/init_menu.json +++ b/backend/dvadmin/system/fixtures/init_menu.json @@ -738,66 +738,5 @@ } ], "menu_button": [] - }, - { - "name": "设备管理", - "icon": "iconfont icon-diannaobangong", - "sort": 4, - "is_link": false, - "is_catalog": true, - "web_path": "", - "component": "", - "component_name": "", - "status": true, - "cache": false, - "visible": true, - "children": [ - { - "name": "网关管理", - "icon": "iconfont icon-LoggedinPC", - "sort": 1, - "is_link": false, - "is_catalog": false, - "web_path": "/swg", - "component": "device/swg/index", - "component_name": "swg", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - }, - { - "name": "联网设备", - "icon": "iconfont icon-putong", - "sort": 2, - "is_link": false, - "is_catalog": false, - "web_path": "/networkDevice", - "component": "device/networkDevice/index", - "component_name": "networkDevice", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - }, - { - "name": "模板信息", - "icon": "iconfont icon-chazhaobiaodanliebiao", - "sort": 3, - "is_link": false, - "is_catalog": false, - "web_path": "/template", - "component": "device/template/index", - "component_name": "templatePage", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - } - ], - "menu_button": [] } ] \ No newline at end of file diff --git a/backend/dvadmin/utils/pagination.py b/backend/dvadmin/utils/pagination.py index 40191ef..52bf143 100644 --- a/backend/dvadmin/utils/pagination.py +++ b/backend/dvadmin/utils/pagination.py @@ -76,8 +76,9 @@ class CustomPagination(PageNumberPagination): ('msg', msg), ('page', page), ('limit', limit), - ('total',total), - ('is_next',is_next), + ('total', total), + ('is_next', is_next), ('is_previous', is_previous), - ('data', data) + ('data', data), + ('permission', self.request.permission_fields) ])) diff --git a/backend/dvadmin/utils/viewset.py b/backend/dvadmin/utils/viewset.py index 47e1c6c..7f9c3a7 100644 --- a/backend/dvadmin/utils/viewset.py +++ b/backend/dvadmin/utils/viewset.py @@ -16,6 +16,8 @@ from dvadmin.utils.filters import DataLevelPermissionsFilter from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSerializerMixin from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse from dvadmin.utils.permission import CustomPermission +from dvadmin.utils.models import get_custom_app_models +from dvadmin.system.models import Columns from django_restql.mixins import QueryArgumentsMixin @@ -61,12 +63,45 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi def get_serializer(self, *args, **kwargs): serializer_class = self.get_serializer_class() kwargs.setdefault('context', self.get_serializer_context()) + # 全部以可见字段为准 + can_see = self.get_column_permission(serializer_class) + # 排除掉序列化器级的字段 + # sub_set = set(serializer_class._declared_fields.keys()) - set(can_see) + # for field in sub_set: + # serializer_class._declared_fields.pop(field) + # if not self.request.user.is_superuser: + # serializer_class.Meta.fields = can_see + # 在分页器中使用 + self.request.permission_fields = can_see if isinstance(self.request.data, list): with transaction.atomic(): return serializer_class(many=True, *args, **kwargs) else: return serializer_class(*args, **kwargs) + def get_column_permission(self, serializer_class): + """获取列权限""" + action_map = { + 'list': 'is_query', + 'retrieve': 'is_query', + 'create': 'is_create', + 'update': 'is_update' + } + finded = False + for app in get_custom_app_models(): + for model in app: + if model['object'] is serializer_class.Meta.model: + finded = True + break + if finded: + break + if finded is False: + return [] + column_permission = Columns.objects.filter(app=model['app'], model=model['model']) + if self.action in action_map: + return [obj.field_name for obj in column_permission if getattr(obj, action_map[self.action])] + return [] + def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, request=request) serializer.is_valid(raise_exception=True) diff --git a/backend/requirements.txt b/backend/requirements.txt index 5500c27..f94509b 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -18,7 +18,7 @@ requests==2.28.2 typing-extensions==4.4.0 smmap==5.0.0 tzlocal==4.1 -channels==4.0.0 +channels==3.0.5 channels-redis==4.0.0 websockets==10.4 user-agents==2.2.0