Commit dbdcdb72 authored by ibuler's avatar ibuler

Merge branch 'dev' of github.com:jumpserver/jumpserver into dev

parents 1ff9f0ea 517a27ea
...@@ -41,40 +41,46 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet): ...@@ -41,40 +41,46 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
pagination_class = LimitOffsetPagination pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
def filter_node(self): def filter_node(self, queryset):
node_id = self.request.query_params.get("node_id") node_id = self.request.query_params.get("node_id")
if not node_id: if not node_id:
return return queryset
node = get_object_or_404(Node, id=node_id) node = get_object_or_404(Node, id=node_id)
show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true') show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true')
if node.is_root(): if node.is_root() and show_current_asset:
if show_current_asset: queryset = queryset.filter(
self.queryset = self.queryset.filter( Q(nodes=node_id) | Q(nodes__isnull=True)
Q(nodes=node_id) | Q(nodes__isnull=True) )
) elif node.is_root() and not show_current_asset:
return pass
if show_current_asset: elif not node.is_root() and show_current_asset:
self.queryset = self.queryset.filter(nodes=node) queryset = queryset.filter(nodes=node)
else: else:
self.queryset = self.queryset.filter( queryset = queryset.filter(
nodes__key__regex='^{}(:[0-9]+)*$'.format(node.key), nodes__key__regex='^{}(:[0-9]+)*$'.format(node.key),
) )
return queryset
def filter_admin_user_id(self): def filter_admin_user_id(self, queryset):
admin_user_id = self.request.query_params.get('admin_user_id') admin_user_id = self.request.query_params.get('admin_user_id')
if admin_user_id: if not admin_user_id:
admin_user = get_object_or_404(AdminUser, id=admin_user_id) return queryset
self.queryset = self.queryset.filter(admin_user=admin_user) admin_user = get_object_or_404(AdminUser, id=admin_user_id)
queryset = queryset.filter(admin_user=admin_user)
return queryset
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.filter_node(queryset)
queryset = self.filter_admin_user_id(queryset)
return queryset
def get_queryset(self): def get_queryset(self):
self.queryset = super().get_queryset()\ queryset = super().get_queryset().distinct()
.prefetch_related('labels', 'nodes')\ queryset = self.get_serializer_class().setup_eager_loading(queryset)
.select_related('admin_user') return queryset
self.filter_admin_user_id()
self.filter_node()
return self.queryset.distinct()
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView): class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
......
...@@ -17,13 +17,13 @@ from rest_framework import generics, mixins, viewsets ...@@ -17,13 +17,13 @@ from rest_framework import generics, mixins, viewsets
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from common.tree import TreeNodeSerializer
from ..hands import IsOrgAdmin from ..hands import IsOrgAdmin
from ..models import Node, Asset from ..models import Node
from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util
from .. import serializers from .. import serializers
...@@ -33,7 +33,8 @@ __all__ = [ ...@@ -33,7 +33,8 @@ __all__ = [
'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi', 'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi',
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi', 'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi',
'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi', 'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
'TestNodeConnectiveApi' 'TestNodeConnectiveApi', 'NodeListAsTreeApi',
'NodeChildrenAsTreeApi',
] ]
...@@ -42,22 +43,89 @@ class NodeViewSet(viewsets.ModelViewSet): ...@@ -42,22 +43,89 @@ class NodeViewSet(viewsets.ModelViewSet):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
def perform_create(self, serializer):
child_key = Node.root().get_next_child_key()
serializer.validated_data["key"] = child_key
serializer.save()
def update(self, request, *args, **kwargs): class NodeListAsTreeApi(generics.ListAPIView):
node = self.get_object() """
if node.is_root(): 获取节点列表树
node_value = node.value [
post_value = request.data.get('value') {
if node_value != post_value: "id": "",
return Response( "name": "",
{"msg": _("You can't update the root node name")}, "pId": "",
status=400 "meta": ""
) }
return super().update(request, *args, **kwargs) ]
"""
permission_classes = (IsOrgAdmin,)
serializer_class = TreeNodeSerializer
def get_queryset(self):
queryset = [node.as_tree_node() for node in Node.objects.all()]
return queryset
def filter_queryset(self, queryset):
if self.request.query_params.get('refresh', '0') == '1':
queryset = self.refresh_nodes(queryset)
return queryset
@staticmethod
def refresh_nodes(queryset):
Node.expire_nodes_assets_amount()
Node.expire_nodes_full_value()
return queryset
class NodeChildrenAsTreeApi(generics.ListAPIView):
"""
节点子节点作为树返回,
[
{
"id": "",
"name": "",
"pId": "",
"meta": ""
}
]
"""
permission_classes = (IsOrgAdmin,)
serializer_class = TreeNodeSerializer
node = None
is_root = False
def get_queryset(self):
node_key = self.request.query_params.get('key')
if node_key:
self.node = Node.objects.get(key=node_key)
queryset = self.node.get_children(with_self=False)
else:
self.is_root = True
self.node = Node.root()
queryset = list(self.node.get_children(with_self=True))
nodes_invalid = Node.objects.exclude(key__startswith=self.node.key)
queryset.extend(list(nodes_invalid))
queryset = [node.as_tree_node() for node in queryset]
return queryset
def filter_assets(self, queryset):
include_assets = self.request.query_params.get('assets', '0') == '1'
if not include_assets:
return queryset
assets = self.node.get_assets()
for asset in assets:
queryset.append(asset.as_tree_node(self.node))
return queryset
def filter_queryset(self, queryset):
queryset = self.filter_assets(queryset)
queryset = self.filter_refresh_nodes(queryset)
return queryset
def filter_refresh_nodes(self, queryset):
if self.request.query_params.get('refresh', '0') == '1':
Node.expire_nodes_assets_amount()
Node.expire_nodes_full_value()
return queryset
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
...@@ -66,19 +134,10 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -66,19 +134,10 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
instance = None instance = None
def counter(self):
values = [
child.value[child.value.rfind(' '):]
for child in self.get_object().get_children()
if child.value.startswith("新节点 ")
]
values = [int(value) for value in values if value.strip().isdigit()]
count = max(values)+1 if values else 1
return count
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
instance = self.get_object()
if not request.data.get("value"): if not request.data.get("value"):
request.data["value"] = _("New node {}").format(self.counter()) request.data["value"] = instance.get_next_child_preset_name()
return super().post(request, *args, **kwargs) return super().post(request, *args, **kwargs)
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
...@@ -90,10 +149,7 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -90,10 +149,7 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
'The same level node name cannot be the same' 'The same level node name cannot be the same'
) )
node = instance.create_child(value=value) node = instance.create_child(value=value)
return Response( return Response(self.serializer_class(instance=node).data, status=201)
{"id": node.id, "key": node.key, "value": node.value},
status=201,
)
def get_object(self): def get_object(self):
pk = self.kwargs.get('pk') or self.request.query_params.get('id') pk = self.kwargs.get('pk') or self.request.query_params.get('id')
...@@ -106,7 +162,6 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -106,7 +162,6 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
def get_queryset(self): def get_queryset(self):
queryset = [] queryset = []
query_all = self.request.query_params.get("all") query_all = self.request.query_params.get("all")
query_assets = self.request.query_params.get('assets')
node = self.get_object() node = self.get_object()
if node is None: if node is None:
...@@ -119,23 +174,8 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -119,23 +174,8 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
else: else:
children = node.get_children() children = node.get_children()
queryset.extend(list(children)) queryset.extend(list(children))
if query_assets:
assets = node.get_assets()
for asset in assets:
node_fake = Node()
node_fake.assets__count = 0
node_fake.id = asset.id
node_fake.is_node = False
node_fake.key = node.key + ':0'
node_fake.value = asset.hostname
queryset.append(node_fake)
queryset = sorted(queryset, key=lambda x: x.is_node, reverse=True)
return queryset return queryset
def get(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
class NodeAssetsApi(generics.ListAPIView): class NodeAssetsApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
......
...@@ -255,6 +255,36 @@ class Asset(OrgModelMixin): ...@@ -255,6 +255,36 @@ class Asset(OrgModelMixin):
}) })
return data return data
def as_tree_node(self, parent_node):
from common.tree import TreeNode
icon_skin = 'file'
if self.platform.lower() == 'windows':
icon_skin = 'windows'
elif self.platform.lower() == 'linux':
icon_skin = 'linux'
data = {
'id': str(self.id),
'name': self.hostname,
'title': self.ip,
'pId': parent_node.key,
'isParent': False,
'open': False,
'iconSkin': icon_skin,
'meta': {
'type': 'asset',
'asset': {
'id': self.id,
'hostname': self.hostname,
'ip': self.ip,
'port': self.port,
'platform': self.platform,
'protocol': self.protocol,
}
}
}
tree_node = TreeNode(**data)
return tree_node
class Meta: class Meta:
unique_together = [('org_id', 'hostname')] unique_together = [('org_id', 'hostname')]
verbose_name = _("Asset") verbose_name = _("Asset")
......
...@@ -5,6 +5,7 @@ import uuid ...@@ -5,6 +5,7 @@ import uuid
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.core.cache import cache from django.core.cache import cache
from orgs.mixins import OrgModelMixin from orgs.mixins import OrgModelMixin
...@@ -103,6 +104,15 @@ class Node(OrgModelMixin): ...@@ -103,6 +104,15 @@ class Node(OrgModelMixin):
key = self._full_value_cache_key.format(self.key) key = self._full_value_cache_key.format(self.key)
cache.delete_pattern(key+'*') cache.delete_pattern(key+'*')
@classmethod
def expire_nodes_full_value(cls, nodes=None):
if nodes:
for node in nodes:
node.expire_full_value()
return
key = cls._full_value_cache_key.format('*')
cache.delete_pattern(key+'*')
@property @property
def level(self): def level(self):
return len(self.key.split(':')) return len(self.key.split(':'))
...@@ -113,6 +123,17 @@ class Node(OrgModelMixin): ...@@ -113,6 +123,17 @@ class Node(OrgModelMixin):
self.save() self.save()
return "{}:{}".format(self.key, mark) return "{}:{}".format(self.key, mark)
def get_next_child_preset_name(self):
name = ugettext("New node")
values = [
child.value[child.value.rfind(' '):]
for child in self.get_children()
if child.value.startswith(name)
]
values = [int(value) for value in values if value.strip().isdigit()]
count = max(values) + 1 if values else 1
return '{} {}'.format(name, count)
def create_child(self, value): def create_child(self, value):
with transaction.atomic(): with transaction.atomic():
child_key = self.get_next_child_key() child_key = self.get_next_child_key()
...@@ -162,7 +183,7 @@ class Node(OrgModelMixin): ...@@ -162,7 +183,7 @@ class Node(OrgModelMixin):
pattern = r'^{0}$|^{0}:'.format(self.key) pattern = r'^{0}$|^{0}:'.format(self.key)
args = [] args = []
kwargs = {} kwargs = {}
if self.is_default_node(): if self.is_root():
args.append(Q(nodes__key__regex=pattern) | Q(nodes=None)) args.append(Q(nodes__key__regex=pattern) | Q(nodes=None))
else: else:
kwargs['nodes__key__regex'] = pattern kwargs['nodes__key__regex'] = pattern
...@@ -256,6 +277,26 @@ class Node(OrgModelMixin): ...@@ -256,6 +277,26 @@ class Node(OrgModelMixin):
defaults = {'value': 'Default'} defaults = {'value': 'Default'}
return cls.objects.get_or_create(defaults=defaults, key='1') return cls.objects.get_or_create(defaults=defaults, key='1')
def as_tree_node(self):
from common.tree import TreeNode
from ..serializers import NodeSerializer
name = '{} ({})'.format(self.value, self.assets_amount)
node_serializer = NodeSerializer(instance=self)
data = {
'id': self.key,
'name': name,
'title': name,
'pId': self.parent_key,
'isParent': True,
'open': self.is_root(),
'meta': {
'node': node_serializer.data,
'type': 'node'
}
}
tree_node = TreeNode(**data)
return tree_node
@classmethod @classmethod
def generate_fake(cls, count=100): def generate_fake(cls, count=100):
import random import random
......
...@@ -9,6 +9,7 @@ from .system_user import AssetSystemUserSerializer ...@@ -9,6 +9,7 @@ from .system_user import AssetSystemUserSerializer
__all__ = [ __all__ = [
'AssetSerializer', 'AssetGrantedSerializer', 'MyAssetGrantedSerializer', 'AssetSerializer', 'AssetGrantedSerializer', 'MyAssetGrantedSerializer',
'AssetAsNodeSerializer',
] ]
...@@ -22,6 +23,13 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): ...@@ -22,6 +23,13 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
validators = [] validators = []
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('labels', 'nodes')\
.select_related('admin_user')
return queryset
def get_field_names(self, declared_fields, info): def get_field_names(self, declared_fields, info):
fields = super().get_field_names(declared_fields, info) fields = super().get_field_names(declared_fields, info)
fields.extend([ fields.extend([
...@@ -30,6 +38,12 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): ...@@ -30,6 +38,12 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
return fields return fields
class AssetAsNodeSerializer(serializers.ModelSerializer):
class Meta:
model = Asset
fields = ['id', 'hostname', 'ip', 'port', 'platform', 'protocol']
class AssetGrantedSerializer(serializers.ModelSerializer): class AssetGrantedSerializer(serializers.ModelSerializer):
""" """
被授权资产的数据结构 被授权资产的数据结构
......
...@@ -8,76 +8,33 @@ from .asset import AssetGrantedSerializer ...@@ -8,76 +8,33 @@ from .asset import AssetGrantedSerializer
__all__ = [ __all__ = [
'NodeSerializer', "NodeGrantedSerializer", "NodeAddChildrenSerializer", 'NodeSerializer', "NodeAddChildrenSerializer",
"NodeAssetsSerializer", "NodeAssetsSerializer",
] ]
class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
"""
授权资产组
"""
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
assets_amount = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()
name = serializers.SerializerMethodField()
class Meta:
model = Node
fields = [
'id', 'key', 'name', 'value', 'parent',
'assets_granted', 'assets_amount', 'org_id',
]
@staticmethod
def get_assets_amount(obj):
return len(obj.assets_granted)
@staticmethod
def get_name(obj):
return obj.name
@staticmethod
def get_parent(obj):
return obj.parent.id
class NodeSerializer(serializers.ModelSerializer): class NodeSerializer(serializers.ModelSerializer):
assets_amount = serializers.IntegerField() assets_amount = serializers.IntegerField(read_only=True)
tree_id = serializers.SerializerMethodField()
tree_parent = serializers.SerializerMethodField()
class Meta: class Meta:
model = Node model = Node
fields = [ fields = [
'id', 'key', 'value', 'assets_amount', 'id', 'key', 'value', 'assets_amount', 'org_id',
'is_node', 'org_id', 'tree_id', 'tree_parent',
] ]
read_only_fields = [ read_only_fields = [
'id', 'key', 'assets_amount', 'is_node', 'id', 'key', 'assets_amount', 'org_id',
'org_id',
] ]
list_serializer_class = BulkListSerializer
def validate(self, data): def validate_value(self, data):
value = data.get('value')
instance = self.instance if self.instance else Node.root() instance = self.instance if self.instance else Node.root()
children = instance.parent.get_children().exclude(key=instance.key) children = instance.parent.get_children().exclude(key=instance.key)
values = [child.value for child in children] values = [child.value for child in children]
if value in values: if data in values:
raise serializers.ValidationError( raise serializers.ValidationError(
'The same level node name cannot be the same' 'The same level node name cannot be the same'
) )
return data return data
@staticmethod
def get_tree_id(obj):
return obj.key
@staticmethod
def get_tree_parent(obj):
return obj.parent_key
class NodeAssetsSerializer(serializers.ModelSerializer): class NodeAssetsSerializer(serializers.ModelSerializer):
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
...@@ -89,3 +46,4 @@ class NodeAssetsSerializer(serializers.ModelSerializer): ...@@ -89,3 +46,4 @@ class NodeAssetsSerializer(serializers.ModelSerializer):
class NodeAddChildrenSerializer(serializers.Serializer): class NodeAddChildrenSerializer(serializers.Serializer):
nodes = serializers.ListField() nodes = serializers.ListField()
...@@ -53,6 +53,8 @@ urlpatterns = [ ...@@ -53,6 +53,8 @@ urlpatterns = [
path('system-user/<uuid:pk>/cmd-filter-rules/', path('system-user/<uuid:pk>/cmd-filter-rules/',
api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'), api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'),
path('nodes/tree/', api.NodeListAsTreeApi.as_view(), name='node-tree'),
path('nodes/children/tree/', api.NodeChildrenAsTreeApi.as_view(), name='node-children-tree'),
path('nodes/<uuid:pk>/children/', path('nodes/<uuid:pk>/children/',
api.NodeChildrenApi.as_view(), name='node-children'), api.NodeChildrenApi.as_view(), name='node-children'),
path('nodes/children/', api.NodeChildrenApi.as_view(), name='node-children-2'), path('nodes/children/', api.NodeChildrenApi.as_view(), name='node-children-2'),
......
...@@ -216,7 +216,6 @@ class AssetExportView(LoginRequiredMixin, View): ...@@ -216,7 +216,6 @@ class AssetExportView(LoginRequiredMixin, View):
return HttpResponse('Json object not valid', status=400) return HttpResponse('Json object not valid', status=400)
if not assets_id: if not assets_id:
print(node_id)
node = get_object_or_none(Node, id=node_id) if node_id else Node.root() node = get_object_or_none(Node, id=node_id) if node_id else Node.root()
assets = node.get_all_assets() assets = node.get_all_assets()
for asset in assets: for asset in assets:
......
...@@ -356,6 +356,7 @@ FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755 ...@@ -356,6 +356,7 @@ FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
# OTP settings # OTP settings
OTP_ISSUER_NAME = CONFIG.OTP_ISSUER_NAME OTP_ISSUER_NAME = CONFIG.OTP_ISSUER_NAME
OTP_VALID_WINDOW = CONFIG.OTP_VALID_WINDOW
# Auth LDAP settings # Auth LDAP settings
AUTH_LDAP = False AUTH_LDAP = False
......
This diff is collapsed.
...@@ -16,7 +16,7 @@ from orgs.utils import set_to_root_org ...@@ -16,7 +16,7 @@ from orgs.utils import set_to_root_org
from .utils import AssetPermissionUtil from .utils import AssetPermissionUtil
from .models import AssetPermission from .models import AssetPermission
from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \ from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \
NodeGrantedSerializer, SystemUser, NodeSerializer SystemUser, NodeSerializer
from . import serializers from . import serializers
from .mixins import AssetsFilterMixin from .mixins import AssetsFilterMixin
...@@ -150,7 +150,7 @@ class UserGrantedNodesWithAssetsApi(AssetsFilterMixin, ListAPIView): ...@@ -150,7 +150,7 @@ class UserGrantedNodesWithAssetsApi(AssetsFilterMixin, ListAPIView):
用户授权的节点并带着节点下资产的api 用户授权的节点并带着节点下资产的api
""" """
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = NodeGrantedSerializer serializer_class = serializers.NodeGrantedSerializer
def change_org_if_need(self): def change_org_if_need(self):
if self.request.user.is_superuser or \ if self.request.user.is_superuser or \
...@@ -360,7 +360,7 @@ class UserGroupGrantedNodesApi(ListAPIView): ...@@ -360,7 +360,7 @@ class UserGroupGrantedNodesApi(ListAPIView):
class UserGroupGrantedNodesWithAssetsApi(ListAPIView): class UserGroupGrantedNodesWithAssetsApi(ListAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = NodeGrantedSerializer serializer_class = serializers.NodeGrantedSerializer
def get_queryset(self): def get_queryset(self):
user_group_id = self.kwargs.get('pk', '') user_group_id = self.kwargs.get('pk', '')
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
from common.permissions import AdminUserRequiredMixin from common.permissions import AdminUserRequiredMixin
from users.models import User, UserGroup from users.models import User, UserGroup
from assets.models import Asset, SystemUser, Node from assets.models import Asset, SystemUser, Node
from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer, NodeSerializer from assets.serializers import AssetGrantedSerializer, NodeSerializer
...@@ -83,6 +83,35 @@ class AssetPermissionNodeSerializer(serializers.ModelSerializer): ...@@ -83,6 +83,35 @@ class AssetPermissionNodeSerializer(serializers.ModelSerializer):
return obj.parent_key return obj.parent_key
class NodeGrantedSerializer(serializers.ModelSerializer):
"""
授权资产组
"""
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
assets_amount = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()
name = serializers.SerializerMethodField()
class Meta:
model = Node
fields = [
'id', 'key', 'name', 'value', 'parent',
'assets_granted', 'assets_amount', 'org_id',
]
@staticmethod
def get_assets_amount(obj):
return len(obj.assets_granted)
@staticmethod
def get_name(obj):
return obj.name
@staticmethod
def get_parent(obj):
return obj.parent.id
class GrantedNodeSerializer(serializers.ModelSerializer): class GrantedNodeSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Node model = Node
......
...@@ -78,58 +78,24 @@ var zTree, table, show = 0; ...@@ -78,58 +78,24 @@ var zTree, table, show = 0;
function onSelected(event, treeNode) { function onSelected(event, treeNode) {
setCookie('node_selected', treeNode.id); setCookie('node_selected', treeNode.id);
var url = table.ajax.url(); var url = table.ajax.url();
if (treeNode.is_node) { if (treeNode.meta.type === 'node') {
url = setUrlParam(url, 'asset', ""); url = setUrlParam(url, 'asset', "");
url = setUrlParam(url, 'node', treeNode.node_id) url = setUrlParam(url, 'node', treeNode.meta.node.id)
} else { } else {
url = setUrlParam(url, 'node', ""); url = setUrlParam(url, 'node', "");
url = setUrlParam(url, 'asset', treeNode.node_id) url = setUrlParam(url, 'asset', treeNode.meta.asset.id)
} }
setCookie('node_selected', treeNode.node_id); setCookie('node_selected', treeNode.node_id);
table.ajax.url(url); table.ajax.url(url);
table.ajax.reload(); table.ajax.reload();
} }
function selectQueryNode() {
var query_node_id = $.getUrlParam("node");
var cookie_node_id = getCookie('node_selected');
var node;
var node_id;
if (query_node_id !== null) {
node_id = query_node_id
} else if (cookie_node_id !== null) {
node_id = cookie_node_id;
}
node = zTree.getNodesByParam("id", node_id, null);
if (node){
zTree.selectNode(node[0]);
node.open = true;
}
}
function filter(treeId, parentNode, childNodes) {
$.each(childNodes, function (index, value) {
value["node_id"] = value["id"];
value["id"] = value["tree_id"];
if (value["tree_id"] !== value["tree_parent"]) {
value["pId"] = value["tree_parent"];
} else {
value["isParent"] = true;
}
value['name'] = value['value'];
value["iconSkin"] = value["is_node"] ? null : 'file';
{#value["pId"] = value["parent"];#}
{#value["name"] = value["value"];#}
value["isParent"] = value["is_node"];
});
return childNodes;
}
function beforeAsync(treeId, treeNode) { function beforeAsync(treeId, treeNode) {
return treeNode.is_node if (treeNode) {
return treeNode.meta.type === 'node'
}
return true
} }
function makeLabel(data) { function makeLabel(data) {
...@@ -235,9 +201,8 @@ function initTree() { ...@@ -235,9 +201,8 @@ function initTree() {
}, },
async: { async: {
enable: true, enable: true,
url: "{% url 'api-assets:node-children-2' %}?assets=1&all=", url: "{% url 'api-assets:node-children-tree' %}?assets=1",
autoParam:["node_id=id", "name=n", "level=lv"], autoParam:["id=key", "name=n", "level=lv"],
dataFilter: filter,
type: 'get' type: 'get'
}, },
callback: { callback: {
...@@ -245,25 +210,7 @@ function initTree() { ...@@ -245,25 +210,7 @@ function initTree() {
beforeAsync: beforeAsync beforeAsync: beforeAsync
} }
}; };
zTree = $.fn.zTree.init($("#assetTree"), setting);
var zNodes = [];
$.get("{% url 'api-assets:node-children-2' %}?assets=1", function(data, status){
$.each(data, function (index, value) {
value["node_id"] = value["id"];
value["id"] = value["tree_id"];
if (value["tree_id"] !== value["tree_parent"]) {
value["pId"] = value["tree_parent"];
}
value["isParent"] = value["is_node"];
value['name'] = value['value'];
value["iconSkin"] = value["is_node"] ? null : 'file';
});
zNodes = data;
$.fn.zTree.init($("#assetTree"), setting, zNodes);
zTree = $.fn.zTree.getZTreeObj("assetTree");
var root = zTree.getNodes()[0];
zTree.expandNode(root);
});
} }
function toggle() { function toggle() {
...@@ -299,10 +246,10 @@ $(document).ready(function(){ ...@@ -299,10 +246,10 @@ $(document).ready(function(){
var _nodes = []; var _nodes = [];
var _assets = []; var _assets = [];
$.each(nodes, function (id, node) { $.each(nodes, function (id, node) {
if (node.is_node) { if (node.meta.type === 'node') {
_nodes.push(node.node_id) _nodes.push(node.meta.node.id)
} else { } else {
_assets.push(node.node_id) _assets.push(node.meta.asset.id)
} }
}); });
url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(","); url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(",");
......
...@@ -292,7 +292,8 @@ def check_otp_code(otp_secret_key, otp_code): ...@@ -292,7 +292,8 @@ def check_otp_code(otp_secret_key, otp_code):
if not otp_secret_key or not otp_code: if not otp_secret_key or not otp_code:
return False return False
totp = pyotp.TOTP(otp_secret_key) totp = pyotp.TOTP(otp_secret_key)
return totp.verify(otp_code) otp_valid_window = settings.OTP_VALID_WINDOW or 0
return totp.verify(otp=otp_code, valid_window=otp_valid_window)
def get_password_check_rules(): def get_password_check_rules():
......
...@@ -100,6 +100,9 @@ class Config: ...@@ -100,6 +100,9 @@ class Config:
} }
AUTH_LDAP_START_TLS = False AUTH_LDAP_START_TLS = False
#
# OTP_VALID_WINDOW = 0
def __init__(self): def __init__(self):
pass pass
...@@ -200,6 +203,10 @@ class DockerConfig(Config): ...@@ -200,6 +203,10 @@ class DockerConfig(Config):
AUTH_LDAP_START_TLS = False AUTH_LDAP_START_TLS = False
#
OTP_VALID_WINDOW = int(os.environ.get("OTP_VALID_WINDOW")) if os.environ.get("OTP_VALID_WINDOW") else 0
# Default using Config settings, you can write if/else for different env # Default using Config settings, you can write if/else for different env
config = DockerConfig() config = DockerConfig()
...@@ -90,6 +90,9 @@ class Config: ...@@ -90,6 +90,9 @@ class Config:
# AUTH_OPENID_CLIENT_ID = 'client-id' # AUTH_OPENID_CLIENT_ID = 'client-id'
# AUTH_OPENID_CLIENT_SECRET = 'client-secret' # AUTH_OPENID_CLIENT_SECRET = 'client-secret'
#
# OTP_VALID_WINDOW = 0
def __init__(self): def __init__(self):
pass pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment