diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index f6cc509b3..04da13061 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -6,8 +6,8 @@ from rest_framework.decorators import action from rest_framework.response import Response from assets import serializers -from assets.models import Asset from assets.filters import IpInFilterBackend, LabelFilterBackend, NodeFilterBackend +from assets.models import Asset from assets.tasks import ( push_accounts_to_assets, test_assets_connectivity_manual, update_assets_hardware_info_manual, verify_accounts_connectivity, @@ -24,6 +24,7 @@ __all__ = [ "AssetViewSet", "AssetTaskCreateApi", "AssetsTaskCreateApi", + 'AssetFilterSet' ] diff --git a/apps/assets/api/mixin.py b/apps/assets/api/mixin.py index 59be2b5f5..2abe967b0 100644 --- a/apps/assets/api/mixin.py +++ b/apps/assets/api/mixin.py @@ -2,7 +2,7 @@ from typing import List from rest_framework.request import Request -from assets.models import Node +from assets.models import Node, PlatformProtocol from assets.utils import get_node_from_request, is_query_node_all_assets from common.utils import lazyproperty, timeit @@ -40,6 +40,9 @@ class SerializeToTreeNodeMixin: @timeit def serialize_assets(self, assets, node_key=None): + sftp_enabled_platform = PlatformProtocol.objects \ + .filter(name='ssh', setting__sftp_enabled=True) \ + .values_list('platform', flat=True).distinct() if node_key is None: get_pid = lambda asset: getattr(asset, 'parent_key', '') else: @@ -58,7 +61,8 @@ class SerializeToTreeNodeMixin: 'meta': { 'type': 'asset', 'data': { - 'org_name': asset.org_name + 'org_name': asset.org_name, + 'sftp': asset.platform_id in sftp_enabled_platform, }, } } diff --git a/apps/perms/api/user_permission/assets/mixin.py b/apps/perms/api/user_permission/assets/mixin.py index e7a584ef4..e95ba7aa1 100644 --- a/apps/perms/api/user_permission/assets/mixin.py +++ b/apps/perms/api/user_permission/assets/mixin.py @@ -1,13 +1,14 @@ -from rest_framework.response import Response from rest_framework.request import Request +from rest_framework.response import Response -from common.utils import get_logger -from users.models import User +from assets.api.asset.asset import AssetFilterSet from assets.api.mixin import SerializeToTreeNodeMixin from assets.models import Asset, Node -from perms.pagination import NodeGrantedAssetPagination, AllGrantedAssetPagination +from common.utils import get_logger from perms import serializers +from perms.pagination import NodeGrantedAssetPagination, AllGrantedAssetPagination from perms.utils.user_permission import UserGrantedAssetsQueryUtils +from users.models import User logger = get_logger(__name__) @@ -32,7 +33,8 @@ class UserAllGrantedAssetsQuerysetMixin: only_fields = serializers.AssetGrantedSerializer.Meta.only_fields pagination_class = AllGrantedAssetPagination ordering_fields = ("name", "address") - ordering = ('name', ) + filterset_class = AssetFilterSet + ordering = ('name',) user: User diff --git a/apps/terminal/const.py b/apps/terminal/const.py index dbfcc0dec..5177f1372 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -44,9 +44,30 @@ class ComponentLoad(TextChoices): return set(dict(cls.choices).keys()) -class HttpMethod(TextChoices): +class WebMethod(TextChoices): web_gui = 'web_gui', 'Web GUI' web_cli = 'web_cli', 'Web CLI' + web_sftp = 'web_sftp', 'Web SFTP' + + @classmethod + def get_methods(cls): + return { + Protocol.ssh: [cls.web_cli, cls.web_sftp], + Protocol.telnet: [cls.web_cli], + Protocol.rdp: [cls.web_gui], + Protocol.vnc: [cls.web_gui], + + Protocol.mysql: [cls.web_cli, cls.web_gui], + Protocol.mariadb: [cls.web_cli, cls.web_gui], + Protocol.oracle: [cls.web_cli, cls.web_gui], + Protocol.postgresql: [cls.web_cli, cls.web_gui], + Protocol.sqlserver: [cls.web_cli, cls.web_gui], + Protocol.redis: [cls.web_cli], + Protocol.mongodb: [cls.web_cli], + + Protocol.k8s: [cls.web_gui], + Protocol.http: [] + } class NativeClient(TextChoices): @@ -67,6 +88,8 @@ class NativeClient(TextChoices): @classmethod def get_native_clients(cls): + # native client 关注的是 endpoint 的 protocol, + # 比如 telnet mysql, koko 都支持,到那时暴露的是 ssh 协议 clients = { Protocol.ssh: { 'default': [cls.ssh], @@ -162,7 +185,7 @@ class TerminalType(TextChoices): def protocols(cls): protocols = { cls.koko: { - 'web_method': HttpMethod.web_cli, + 'web_methods': [WebMethod.web_cli, WebMethod.web_sftp], 'listen': [Protocol.ssh, Protocol.http], 'support': [ Protocol.ssh, Protocol.telnet, @@ -174,7 +197,7 @@ class TerminalType(TextChoices): 'match': 'm2m' }, cls.omnidb: { - 'web_method': HttpMethod.web_gui, + 'web_methods': [WebMethod.web_gui], 'listen': [Protocol.http], 'support': [ Protocol.mysql, Protocol.postgresql, Protocol.oracle, @@ -183,7 +206,7 @@ class TerminalType(TextChoices): 'match': 'm2m' }, cls.lion: { - 'web_method': HttpMethod.web_gui, + 'web_methods': [WebMethod.web_gui], 'listen': [Protocol.http], 'support': [Protocol.rdp, Protocol.vnc], 'match': 'm2m' @@ -216,6 +239,7 @@ class TerminalType(TextChoices): @classmethod def get_protocols_connect_methods(cls, os): methods = defaultdict(list) + web_methods = WebMethod.get_methods() native_methods = NativeClient.get_methods(os) applet_methods = AppletMethod.get_methods() @@ -229,16 +253,6 @@ class TerminalType(TextChoices): listen = component_protocol['listen'] for listen_protocol in listen: - if listen_protocol == Protocol.http: - web_protocol = component_protocol['web_method'] - methods[protocol.value].append({ - 'value': web_protocol.value, - 'label': web_protocol.label, - 'endpoint_protocol': 'http', - 'type': 'web', - 'component': component.value, - }) - # Native method methods[protocol.value].extend([ { @@ -250,6 +264,20 @@ class TerminalType(TextChoices): for method in native_methods[listen_protocol] ]) + protocol_web_methods = set(web_methods.get(protocol, [])) \ + & set(component_protocol.get('web_methods', [])) + print("protocol_web_methods", protocol, protocol_web_methods) + methods[protocol.value].extend([ + { + 'component': component.value, + 'type': 'web', + 'endpoint_protocol': 'http', + 'value': method.value, + 'label': method.label, + } + for method in protocol_web_methods + ]) + for protocol, applet_methods in applet_methods.items(): for method in applet_methods: method['type'] = 'applet'