mirror of https://github.com/jumpserver/jumpserver
perf: perm account 返回 alias
parent
acfce4961c
commit
cb7b31e8b8
|
@ -1,11 +1,12 @@
|
||||||
from .mixin import *
|
|
||||||
from .category import *
|
|
||||||
from .platform import *
|
|
||||||
from .asset import *
|
|
||||||
from .label import *
|
|
||||||
from .account import *
|
from .account import *
|
||||||
from .node import *
|
from .asset import *
|
||||||
from .domain import *
|
|
||||||
from .automations import *
|
from .automations import *
|
||||||
from .gathered_user import *
|
from .category import *
|
||||||
|
from .domain import *
|
||||||
from .favorite_asset import *
|
from .favorite_asset import *
|
||||||
|
from .gathered_user import *
|
||||||
|
from .label import *
|
||||||
|
from .mixin import *
|
||||||
|
from .node import *
|
||||||
|
from .platform import *
|
||||||
|
from .tree import *
|
||||||
|
|
|
@ -1,43 +1,37 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
from functools import partial
|
|
||||||
from collections import namedtuple, defaultdict
|
from collections import namedtuple, defaultdict
|
||||||
from django.core.exceptions import PermissionDenied
|
from functools import partial
|
||||||
|
|
||||||
from rest_framework import status
|
|
||||||
from rest_framework.generics import get_object_or_404
|
|
||||||
from rest_framework.serializers import ValidationError
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework.decorators import action
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.db.models.signals import m2m_changed
|
from django.db.models.signals import m2m_changed
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.serializers import ValidationError
|
||||||
|
|
||||||
from common.const.http import POST
|
|
||||||
from common.exceptions import SomeoneIsDoingThis
|
|
||||||
from common.const.signals import PRE_REMOVE, POST_REMOVE
|
|
||||||
from common.mixins.api import SuggestionMixin
|
|
||||||
from assets.models import Asset
|
from assets.models import Asset
|
||||||
|
from common.const.http import POST
|
||||||
|
from common.const.signals import PRE_REMOVE, POST_REMOVE
|
||||||
|
from common.exceptions import SomeoneIsDoingThis
|
||||||
|
from common.mixins.api import SuggestionMixin
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from common.tree import TreeNodeSerializer
|
|
||||||
from orgs.mixins.api import OrgBulkModelViewSet
|
|
||||||
from orgs.mixins import generics
|
from orgs.mixins import generics
|
||||||
|
from orgs.mixins.api import OrgBulkModelViewSet
|
||||||
from orgs.utils import current_org
|
from orgs.utils import current_org
|
||||||
|
from .. import serializers
|
||||||
from ..models import Node
|
from ..models import Node
|
||||||
from ..tasks import (
|
from ..tasks import (
|
||||||
update_node_assets_hardware_info_manual,
|
update_node_assets_hardware_info_manual,
|
||||||
test_node_assets_connectivity_manual,
|
test_node_assets_connectivity_manual,
|
||||||
check_node_assets_amount_task
|
check_node_assets_amount_task
|
||||||
)
|
)
|
||||||
from .. import serializers
|
|
||||||
from ..const import AllTypes
|
|
||||||
from .mixin import SerializeToTreeNodeMixin
|
|
||||||
from assets.locks import NodeAddChildrenLock
|
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi',
|
'NodeViewSet', 'NodeAssetsApi', 'NodeAddAssetsApi',
|
||||||
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'MoveAssetsToNodeApi',
|
'NodeRemoveAssetsApi', 'MoveAssetsToNodeApi',
|
||||||
'NodeAddChildrenApi', 'NodeListAsTreeApi', 'NodeChildrenAsTreeApi',
|
'NodeAddChildrenApi', 'NodeTaskCreateApi',
|
||||||
'NodeTaskCreateApi', 'CategoryTreeApi',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,153 +68,6 @@ class NodeViewSet(SuggestionMixin, OrgBulkModelViewSet):
|
||||||
return super().destroy(request, *args, **kwargs)
|
return super().destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class NodeListAsTreeApi(generics.ListAPIView):
|
|
||||||
"""
|
|
||||||
获取节点列表树
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": "",
|
|
||||||
"name": "",
|
|
||||||
"pId": "",
|
|
||||||
"meta": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
model = Node
|
|
||||||
serializer_class = TreeNodeSerializer
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def to_tree_queryset(queryset):
|
|
||||||
queryset = [node.as_tree_node() for node in queryset]
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
|
||||||
queryset = super().filter_queryset(queryset)
|
|
||||||
queryset = self.to_tree_queryset(queryset)
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class NodeChildrenApi(generics.ListCreateAPIView):
|
|
||||||
serializer_class = serializers.NodeSerializer
|
|
||||||
search_fields = ('value',)
|
|
||||||
|
|
||||||
instance = None
|
|
||||||
is_initial = False
|
|
||||||
|
|
||||||
def initial(self, request, *args, **kwargs):
|
|
||||||
self.instance = self.get_object()
|
|
||||||
return super().initial(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
|
||||||
with NodeAddChildrenLock(self.instance):
|
|
||||||
data = serializer.validated_data
|
|
||||||
_id = data.get("id")
|
|
||||||
value = data.get("value")
|
|
||||||
if not value:
|
|
||||||
value = self.instance.get_next_child_preset_name()
|
|
||||||
node = self.instance.create_child(value=value, _id=_id)
|
|
||||||
# 避免查询 full value
|
|
||||||
node._full_value = node.value
|
|
||||||
serializer.instance = node
|
|
||||||
|
|
||||||
def get_object(self):
|
|
||||||
pk = self.kwargs.get('pk') or self.request.query_params.get('id')
|
|
||||||
key = self.request.query_params.get("key")
|
|
||||||
|
|
||||||
if not pk and not key:
|
|
||||||
self.is_initial = True
|
|
||||||
if current_org.is_root():
|
|
||||||
node = None
|
|
||||||
else:
|
|
||||||
node = Node.org_root()
|
|
||||||
return node
|
|
||||||
if pk:
|
|
||||||
node = get_object_or_404(Node, pk=pk)
|
|
||||||
else:
|
|
||||||
node = get_object_or_404(Node, key=key)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def get_org_root_queryset(self, query_all):
|
|
||||||
if query_all:
|
|
||||||
return Node.objects.all()
|
|
||||||
else:
|
|
||||||
return Node.org_root_nodes()
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
query_all = self.request.query_params.get("all", "0") == "all"
|
|
||||||
|
|
||||||
if self.is_initial and current_org.is_root():
|
|
||||||
return self.get_org_root_queryset(query_all)
|
|
||||||
|
|
||||||
if self.is_initial:
|
|
||||||
with_self = True
|
|
||||||
else:
|
|
||||||
with_self = False
|
|
||||||
|
|
||||||
if not self.instance:
|
|
||||||
return Node.objects.none()
|
|
||||||
|
|
||||||
if query_all:
|
|
||||||
queryset = self.instance.get_all_children(with_self=with_self)
|
|
||||||
else:
|
|
||||||
queryset = self.instance.get_children(with_self=with_self)
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi):
|
|
||||||
"""
|
|
||||||
节点子节点作为树返回,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": "",
|
|
||||||
"name": "",
|
|
||||||
"pId": "",
|
|
||||||
"meta": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
"""
|
|
||||||
model = Node
|
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
|
||||||
if not self.request.GET.get('search'):
|
|
||||||
return queryset
|
|
||||||
queryset = super().filter_queryset(queryset)
|
|
||||||
queryset = self.model.get_ancestor_queryset(queryset)
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
|
||||||
nodes = self.filter_queryset(self.get_queryset()).order_by('value')
|
|
||||||
nodes = self.serialize_nodes(nodes, with_asset_amount=True)
|
|
||||||
assets = self.get_assets()
|
|
||||||
data = [*nodes, *assets]
|
|
||||||
return Response(data=data)
|
|
||||||
|
|
||||||
def get_assets(self):
|
|
||||||
include_assets = self.request.query_params.get('assets', '0') == '1'
|
|
||||||
if not self.instance or not include_assets:
|
|
||||||
return []
|
|
||||||
assets = self.instance.get_assets().only(
|
|
||||||
"id", "name", "address", "platform_id",
|
|
||||||
"org_id", "is_active",
|
|
||||||
).prefetch_related('platform')
|
|
||||||
return self.serialize_assets(assets, self.instance.key)
|
|
||||||
|
|
||||||
|
|
||||||
class CategoryTreeApi(SerializeToTreeNodeMixin, generics.ListAPIView):
|
|
||||||
serializer_class = TreeNodeSerializer
|
|
||||||
|
|
||||||
def check_permissions(self, request):
|
|
||||||
if not request.user.has_perm('assets.view_asset'):
|
|
||||||
raise PermissionDenied
|
|
||||||
return True
|
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
|
||||||
nodes = AllTypes.to_tree_nodes()
|
|
||||||
serializer = self.get_serializer(nodes, many=True)
|
|
||||||
return Response(data=serializer.data)
|
|
||||||
|
|
||||||
|
|
||||||
class NodeAssetsApi(generics.ListAPIView):
|
class NodeAssetsApi(generics.ListAPIView):
|
||||||
serializer_class = serializers.AssetSerializer
|
serializer_class = serializers.AssetSerializer
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from assets.locks import NodeAddChildrenLock
|
||||||
|
from common.tree import TreeNodeSerializer
|
||||||
|
from common.utils import get_logger
|
||||||
|
from orgs.mixins import generics
|
||||||
|
from orgs.utils import current_org
|
||||||
|
from .mixin import SerializeToTreeNodeMixin
|
||||||
|
from .. import serializers
|
||||||
|
from ..const import AllTypes
|
||||||
|
from ..models import Node
|
||||||
|
|
||||||
|
logger = get_logger(__file__)
|
||||||
|
__all__ = [
|
||||||
|
'NodeChildrenApi',
|
||||||
|
'NodeListAsTreeApi',
|
||||||
|
'NodeChildrenAsTreeApi',
|
||||||
|
'CategoryTreeApi',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class NodeListAsTreeApi(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
获取节点列表树
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "",
|
||||||
|
"name": "",
|
||||||
|
"pId": "",
|
||||||
|
"meta": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
model = Node
|
||||||
|
serializer_class = TreeNodeSerializer
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_tree_queryset(queryset):
|
||||||
|
queryset = [node.as_tree_node() for node in queryset]
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def filter_queryset(self, queryset):
|
||||||
|
queryset = super().filter_queryset(queryset)
|
||||||
|
queryset = self.to_tree_queryset(queryset)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class NodeChildrenApi(generics.ListCreateAPIView):
|
||||||
|
serializer_class = serializers.NodeSerializer
|
||||||
|
search_fields = ('value',)
|
||||||
|
|
||||||
|
instance = None
|
||||||
|
is_initial = False
|
||||||
|
|
||||||
|
def initial(self, request, *args, **kwargs):
|
||||||
|
self.instance = self.get_object()
|
||||||
|
return super().initial(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def perform_create(self, serializer):
|
||||||
|
with NodeAddChildrenLock(self.instance):
|
||||||
|
data = serializer.validated_data
|
||||||
|
_id = data.get("id")
|
||||||
|
value = data.get("value")
|
||||||
|
if not value:
|
||||||
|
value = self.instance.get_next_child_preset_name()
|
||||||
|
node = self.instance.create_child(value=value, _id=_id)
|
||||||
|
# 避免查询 full value
|
||||||
|
node._full_value = node.value
|
||||||
|
serializer.instance = node
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
pk = self.kwargs.get('pk') or self.request.query_params.get('id')
|
||||||
|
key = self.request.query_params.get("key")
|
||||||
|
|
||||||
|
if not pk and not key:
|
||||||
|
self.is_initial = True
|
||||||
|
if current_org.is_root():
|
||||||
|
node = None
|
||||||
|
else:
|
||||||
|
node = Node.org_root()
|
||||||
|
return node
|
||||||
|
if pk:
|
||||||
|
node = get_object_or_404(Node, pk=pk)
|
||||||
|
else:
|
||||||
|
node = get_object_or_404(Node, key=key)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def get_org_root_queryset(self, query_all):
|
||||||
|
if query_all:
|
||||||
|
return Node.objects.all()
|
||||||
|
else:
|
||||||
|
return Node.org_root_nodes()
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
query_all = self.request.query_params.get("all", "0") == "all"
|
||||||
|
|
||||||
|
if self.is_initial and current_org.is_root():
|
||||||
|
return self.get_org_root_queryset(query_all)
|
||||||
|
|
||||||
|
if self.is_initial:
|
||||||
|
with_self = True
|
||||||
|
else:
|
||||||
|
with_self = False
|
||||||
|
|
||||||
|
if not self.instance:
|
||||||
|
return Node.objects.none()
|
||||||
|
|
||||||
|
if query_all:
|
||||||
|
queryset = self.instance.get_all_children(with_self=with_self)
|
||||||
|
else:
|
||||||
|
queryset = self.instance.get_children(with_self=with_self)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi):
|
||||||
|
"""
|
||||||
|
节点子节点作为树返回,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "",
|
||||||
|
"name": "",
|
||||||
|
"pId": "",
|
||||||
|
"meta": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
"""
|
||||||
|
model = Node
|
||||||
|
|
||||||
|
def filter_queryset(self, queryset):
|
||||||
|
if not self.request.GET.get('search'):
|
||||||
|
return queryset
|
||||||
|
queryset = super().filter_queryset(queryset)
|
||||||
|
queryset = self.model.get_ancestor_queryset(queryset)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
nodes = self.filter_queryset(self.get_queryset()).order_by('value')
|
||||||
|
nodes = self.serialize_nodes(nodes, with_asset_amount=True)
|
||||||
|
assets = self.get_assets()
|
||||||
|
data = [*nodes, *assets]
|
||||||
|
return Response(data=data)
|
||||||
|
|
||||||
|
def get_assets(self):
|
||||||
|
include_assets = self.request.query_params.get('assets', '0') == '1'
|
||||||
|
if not self.instance or not include_assets:
|
||||||
|
return []
|
||||||
|
assets = self.instance.get_assets().only(
|
||||||
|
"id", "name", "address", "platform_id",
|
||||||
|
"org_id", "is_active",
|
||||||
|
).prefetch_related('platform')
|
||||||
|
return self.serialize_assets(assets, self.instance.key)
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryTreeApi(SerializeToTreeNodeMixin, generics.ListAPIView):
|
||||||
|
serializer_class = TreeNodeSerializer
|
||||||
|
|
||||||
|
def check_permissions(self, request):
|
||||||
|
if not request.user.has_perm('assets.view_asset'):
|
||||||
|
raise PermissionDenied
|
||||||
|
return True
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
if request.query_params.get('key'):
|
||||||
|
nodes = []
|
||||||
|
else:
|
||||||
|
nodes = AllTypes.to_tree_nodes()
|
||||||
|
serializer = self.get_serializer(nodes, many=True)
|
||||||
|
return Response(data=serializer.data)
|
|
@ -1,14 +1,14 @@
|
||||||
|
from collections import defaultdict
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
from common.db.models import ChoicesMixin
|
from common.db.models import ChoicesMixin
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
|
|
||||||
from .category import Category
|
from .category import Category
|
||||||
from .host import HostTypes
|
|
||||||
from .device import DeviceTypes
|
|
||||||
from .database import DatabaseTypes
|
|
||||||
from .web import WebTypes
|
|
||||||
from .cloud import CloudTypes
|
from .cloud import CloudTypes
|
||||||
|
from .database import DatabaseTypes
|
||||||
|
from .device import DeviceTypes
|
||||||
|
from .host import HostTypes
|
||||||
|
from .web import WebTypes
|
||||||
|
|
||||||
|
|
||||||
class AllTypes(ChoicesMixin):
|
class AllTypes(ChoicesMixin):
|
||||||
|
@ -124,7 +124,7 @@ class AllTypes(ChoicesMixin):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def choice_to_node(choice, pid, opened=True, is_parent=True, meta=None):
|
def choice_to_node(choice, pid, opened=True, is_parent=True, meta=None):
|
||||||
node = TreeNode(**{
|
node = TreeNode(**{
|
||||||
'id': choice.name,
|
'id': pid + '_' + choice.name,
|
||||||
'name': choice.label,
|
'name': choice.label,
|
||||||
'title': choice.label,
|
'title': choice.label,
|
||||||
'pId': pid,
|
'pId': pid,
|
||||||
|
@ -135,16 +135,57 @@ class AllTypes(ChoicesMixin):
|
||||||
node.meta = meta
|
node.meta = meta
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def platform_to_node(cls, p, pid):
|
||||||
|
node = TreeNode(**{
|
||||||
|
'id': '{}'.format(p.id),
|
||||||
|
'name': p.name,
|
||||||
|
'title': p.name,
|
||||||
|
'pId': pid,
|
||||||
|
'isParent': True,
|
||||||
|
'meta': {
|
||||||
|
'type': 'platform'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return node
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def to_tree_nodes(cls):
|
def to_tree_nodes(cls):
|
||||||
root = TreeNode(id='ROOT', name='类型节点', title='类型节点')
|
from ..models import Asset, Platform
|
||||||
|
asset_platforms = Asset.objects.all().values_list('platform_id', flat=True)
|
||||||
|
platform_count = defaultdict(int)
|
||||||
|
for platform_id in asset_platforms:
|
||||||
|
platform_count[platform_id] += 1
|
||||||
|
|
||||||
|
category_type_mapper = defaultdict(int)
|
||||||
|
platforms = Platform.objects.all()
|
||||||
|
tp_platforms = defaultdict(list)
|
||||||
|
|
||||||
|
for p in platforms:
|
||||||
|
category_type_mapper[p.category + '_' + p.type] += platform_count[p.id]
|
||||||
|
category_type_mapper[p.category] += platform_count[p.id]
|
||||||
|
tp_platforms[p.category + '_' + p.type].append(p)
|
||||||
|
|
||||||
|
root = TreeNode(id='ROOT', name='所有类型', title='所有类型', open=True, isParent=True)
|
||||||
nodes = [root]
|
nodes = [root]
|
||||||
for category, types in cls.category_types():
|
for category, types in cls.category_types():
|
||||||
category_node = cls.choice_to_node(category, 'ROOT', meta={'type': 'category'})
|
meta = {'type': 'category', 'category': category.value}
|
||||||
|
category_node = cls.choice_to_node(category, 'ROOT', meta=meta)
|
||||||
|
category_count = category_type_mapper.get(category, 0)
|
||||||
|
category_node.name += f'({category_count})'
|
||||||
nodes.append(category_node)
|
nodes.append(category_node)
|
||||||
|
|
||||||
for tp in types:
|
for tp in types:
|
||||||
tp_node = cls.choice_to_node(tp, category_node.id, meta={'type': 'type'})
|
meta = {'type': 'type', 'category': category.value, '_type': tp.value}
|
||||||
|
tp_node = cls.choice_to_node(tp, category_node.id, opened=False, meta=meta)
|
||||||
|
tp_count = category_type_mapper.get(category + '_' + tp, 0)
|
||||||
|
tp_node.name += f'({tp_count})'
|
||||||
nodes.append(tp_node)
|
nodes.append(tp_node)
|
||||||
|
|
||||||
|
for p in tp_platforms.get(category + '_' + tp, []):
|
||||||
|
platform_node = cls.platform_to_node(p, tp_node.id)
|
||||||
|
platform_node.name += f'({platform_count.get(p.id, 0)})'
|
||||||
|
nodes.append(platform_node)
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -253,8 +294,3 @@ class AllTypes(ChoicesMixin):
|
||||||
print("\t- Update platform: {}".format(platform.name))
|
print("\t- Update platform: {}".format(platform.name))
|
||||||
platform_data = cls.get_type_default_platform(platform.category, platform.type)
|
platform_data = cls.get_type_default_platform(platform.category, platform.type)
|
||||||
cls.create_or_update_by_platform_data(platform.name, platform_data)
|
cls.create_or_update_by_platform_data(platform.name, platform_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from simple_history.models import HistoricalRecords
|
from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
from common.utils import lazyproperty
|
from common.utils import lazyproperty
|
||||||
|
|
||||||
from .base import AbsConnectivity, BaseAccount
|
from .base import AbsConnectivity, BaseAccount
|
||||||
|
|
||||||
__all__ = ['Account', 'AccountTemplate']
|
__all__ = ['Account', 'AccountTemplate']
|
||||||
|
@ -74,6 +73,12 @@ class Account(AbsConnectivity, BaseAccount):
|
||||||
def platform(self):
|
def platform(self):
|
||||||
return self.asset.platform
|
return self.asset.platform
|
||||||
|
|
||||||
|
@lazyproperty
|
||||||
|
def alias(self):
|
||||||
|
if self.username.startswith('@'):
|
||||||
|
return self.username
|
||||||
|
return self.name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}'.format(self.username)
|
return '{}'.format(self.username)
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView
|
||||||
permed_account = util.validate_permission(user, asset, account_name)
|
permed_account = util.validate_permission(user, asset, account_name)
|
||||||
|
|
||||||
if not permed_account or not permed_account.actions:
|
if not permed_account or not permed_account.actions:
|
||||||
msg = 'user `{}` not has asset `{}` permission for login `{}`'.format(
|
msg = 'user `{}` not has asset `{}` permission for account `{}`'.format(
|
||||||
user, asset, account_name
|
user, asset, account_name
|
||||||
)
|
)
|
||||||
raise PermissionDenied(msg)
|
raise PermissionDenied(msg)
|
||||||
|
|
|
@ -6,14 +6,10 @@ from django.db.models import Q
|
||||||
from rest_framework.generics import ListAPIView
|
from rest_framework.generics import ListAPIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from common.utils import lazyproperty
|
|
||||||
from perms.models import AssetPermission
|
|
||||||
from assets.models import Asset, Node
|
|
||||||
from . import user_permission as uapi
|
|
||||||
from perms import serializers
|
|
||||||
from perms.utils import PermAccountUtil
|
|
||||||
from assets.api.mixin import SerializeToTreeNodeMixin
|
from assets.api.mixin import SerializeToTreeNodeMixin
|
||||||
from users.models import UserGroup
|
from assets.models import Asset, Node
|
||||||
|
from perms import serializers
|
||||||
|
from perms.models import AssetPermission
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'UserGroupGrantedAssetsApi', 'UserGroupGrantedNodesApi',
|
'UserGroupGrantedAssetsApi', 'UserGroupGrantedNodesApi',
|
||||||
|
@ -115,7 +111,7 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView):
|
||||||
|
|
||||||
|
|
||||||
class UserGroupGrantedNodesApi(ListAPIView):
|
class UserGroupGrantedNodesApi(ListAPIView):
|
||||||
serializer_class = serializers.NodeGrantedSerializer
|
serializer_class = serializers.NodePermedSerializer
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
'list': 'perms.view_usergroupassets',
|
'list': 'perms.view_usergroupassets',
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
from rest_framework.generics import ListAPIView
|
from rest_framework.generics import ListAPIView
|
||||||
|
|
||||||
from assets.models import Node
|
from assets.models import Node
|
||||||
|
from common.utils import get_logger, lazyproperty
|
||||||
from perms import serializers
|
from perms import serializers
|
||||||
from perms.utils.user_permission import UserGrantedNodesQueryUtils
|
from perms.utils.user_permission import UserGrantedNodesQueryUtils
|
||||||
from common.utils import get_logger, lazyproperty
|
|
||||||
|
|
||||||
from .mixin import SelfOrPKUserMixin
|
from .mixin import SelfOrPKUserMixin
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
@ -19,7 +19,7 @@ __all__ = [
|
||||||
|
|
||||||
|
|
||||||
class BaseUserPermedNodesApi(SelfOrPKUserMixin, ListAPIView):
|
class BaseUserPermedNodesApi(SelfOrPKUserMixin, ListAPIView):
|
||||||
serializer_class = serializers.NodeGrantedSerializer
|
serializer_class = serializers.NodePermedSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
|
@ -37,12 +37,14 @@ class BaseUserPermedNodesApi(SelfOrPKUserMixin, ListAPIView):
|
||||||
|
|
||||||
class UserAllPermedNodesApi(BaseUserPermedNodesApi):
|
class UserAllPermedNodesApi(BaseUserPermedNodesApi):
|
||||||
""" 用户授权的节点 """
|
""" 用户授权的节点 """
|
||||||
|
|
||||||
def get_nodes(self):
|
def get_nodes(self):
|
||||||
return self.query_node_util.get_whole_tree_nodes()
|
return self.query_node_util.get_whole_tree_nodes()
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodeChildrenApi(BaseUserPermedNodesApi):
|
class UserPermedNodeChildrenApi(BaseUserPermedNodesApi):
|
||||||
""" 用户授权的节点下的子节点 """
|
""" 用户授权的节点下的子节点 """
|
||||||
|
|
||||||
def get_nodes(self):
|
def get_nodes(self):
|
||||||
key = self.request.query_params.get('key')
|
key = self.request.query_params.get('key')
|
||||||
nodes = self.query_node_util.get_node_children(key)
|
nodes = self.query_node_util.get_node_children(key)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from common.drf.fields import ObjectRelatedField, LabeledChoiceField
|
||||||
from perms.serializers.permission import ActionChoicesField
|
from perms.serializers.permission import ActionChoicesField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'NodeGrantedSerializer', 'AssetPermedSerializer',
|
'NodePermedSerializer', 'AssetPermedSerializer',
|
||||||
'AccountsPermedSerializer'
|
'AccountsPermedSerializer'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -26,15 +26,14 @@ class AssetPermedSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
only_fields = [
|
only_fields = [
|
||||||
"id", "name", "address",
|
"id", "name", "address", 'domain', 'platform',
|
||||||
'domain', 'platform',
|
|
||||||
"comment", "org_id", "is_active",
|
"comment", "org_id", "is_active",
|
||||||
]
|
]
|
||||||
fields = only_fields + ['protocols', 'category', 'type', 'specific'] + ['org_name']
|
fields = only_fields + ['protocols', 'category', 'type', 'specific'] + ['org_name']
|
||||||
read_only_fields = fields
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
class NodeGrantedSerializer(serializers.ModelSerializer):
|
class NodePermedSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Node
|
model = Node
|
||||||
fields = [
|
fields = [
|
||||||
|
@ -48,6 +47,8 @@ class AccountsPermedSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ['id', 'name', 'has_username', 'username',
|
fields = [
|
||||||
'has_secret', 'secret_type', 'actions']
|
'alias', 'name', 'username', 'has_username',
|
||||||
|
'has_secret', 'secret_type', 'actions'
|
||||||
|
]
|
||||||
read_only_fields = fields
|
read_only_fields = fields
|
||||||
|
|
|
@ -16,7 +16,7 @@ class PermAccountUtil(AssetPermissionUtil):
|
||||||
:param account_name: 可能是 @USER @INPUT 字符串
|
:param account_name: 可能是 @USER @INPUT 字符串
|
||||||
"""
|
"""
|
||||||
permed_accounts = self.get_permed_accounts_for_user(user, asset)
|
permed_accounts = self.get_permed_accounts_for_user(user, asset)
|
||||||
accounts_mapper = {account.name: account for account in permed_accounts}
|
accounts_mapper = {account.alias: account for account in permed_accounts}
|
||||||
account = accounts_mapper.get(account_name)
|
account = accounts_mapper.get(account_name)
|
||||||
return account
|
return account
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue