Unverified Commit 1fe18e80 authored by 老广's avatar 老广 Committed by GitHub

Bugfix (#3153)

* [Update] 修改一部分bug

* [Update] 修改一些
parent de1a08a5
...@@ -63,15 +63,15 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet): ...@@ -63,15 +63,15 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
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() and show_current_asset: if node.is_org_root() and show_current_asset:
queryset = queryset.filter( queryset = queryset.filter(
Q(nodes=node_id) | Q(nodes__isnull=True) Q(nodes=node_id) | Q(nodes__isnull=True)
).distinct() ).distinct()
# 当前节点是顶层节点,显示所有资产 # 当前节点是顶层节点,显示所有资产
elif node.is_root() and not show_current_asset: elif node.is_org_root() and not show_current_asset:
return queryset return queryset
# 当前节点不是鼎城节点,只显示直接资产 # 当前节点不是鼎城节点,只显示直接资产
elif not node.is_root() and show_current_asset: elif not node.is_org_root() and show_current_asset:
queryset = queryset.filter(nodes=node) queryset = queryset.filter(nodes=node)
else: else:
children = node.get_all_children(with_self=True) children = node.get_all_children(with_self=True)
......
...@@ -50,13 +50,13 @@ class NodeViewSet(OrgModelViewSet): ...@@ -50,13 +50,13 @@ class NodeViewSet(OrgModelViewSet):
# 仅支持根节点指直接创建,子节点下的节点需要通过children接口创建 # 仅支持根节点指直接创建,子节点下的节点需要通过children接口创建
def perform_create(self, serializer): def perform_create(self, serializer):
child_key = Node.root().get_next_child_key() child_key = Node.org_root().get_next_child_key()
serializer.validated_data["key"] = child_key serializer.validated_data["key"] = child_key
serializer.save() serializer.save()
def perform_update(self, serializer): def perform_update(self, serializer):
node = self.get_object() node = self.get_object()
if node.is_root() and node.value != serializer.validated_data['value']: if node.is_org_root() and node.value != serializer.validated_data['value']:
msg = _("You can't update the root node name") msg = _("You can't update the root node name")
raise ValidationError({"error": msg}) raise ValidationError({"error": msg})
return super().perform_update(serializer) return super().perform_update(serializer)
...@@ -97,6 +97,7 @@ class NodeChildrenApi(generics.ListCreateAPIView): ...@@ -97,6 +97,7 @@ class NodeChildrenApi(generics.ListCreateAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
instance = None instance = None
is_initial = False
def initial(self, request, *args, **kwargs): def initial(self, request, *args, **kwargs):
self.instance = self.get_object() self.instance = self.get_object()
...@@ -117,7 +118,8 @@ class NodeChildrenApi(generics.ListCreateAPIView): ...@@ -117,7 +118,8 @@ class NodeChildrenApi(generics.ListCreateAPIView):
pk = self.kwargs.get('pk') or self.request.query_params.get('id') pk = self.kwargs.get('pk') or self.request.query_params.get('id')
key = self.request.query_params.get("key") key = self.request.query_params.get("key")
if not pk and not key: if not pk and not key:
node = Node.root() node = Node.org_root()
self.is_initial = True
return node return node
if pk: if pk:
node = get_object_or_404(Node, pk=pk) node = get_object_or_404(Node, pk=pk)
...@@ -130,7 +132,7 @@ class NodeChildrenApi(generics.ListCreateAPIView): ...@@ -130,7 +132,7 @@ class NodeChildrenApi(generics.ListCreateAPIView):
if not self.instance: if not self.instance:
return Node.objects.none() return Node.objects.none()
if self.instance.is_root(): if self.is_initial:
with_self = True with_self = True
else: else:
with_self = False with_self = False
...@@ -234,7 +236,7 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView): ...@@ -234,7 +236,7 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
def perform_update(self, serializer): def perform_update(self, serializer):
assets = serializer.validated_data.get('assets') assets = serializer.validated_data.get('assets')
instance = self.get_object() instance = self.get_object()
if instance != Node.root(): if instance != Node.org_root():
instance.assets.remove(*tuple(assets)) instance.assets.remove(*tuple(assets))
else: else:
assets = [asset for asset in assets if asset.nodes.count() > 1] assets = [asset for asset in assets if asset.nodes.count() > 1]
...@@ -287,5 +289,4 @@ class RefreshAssetsAmount(APIView): ...@@ -287,5 +289,4 @@ class RefreshAssetsAmount(APIView):
model = Node model = Node
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.model.expire_nodes_assets_amount()
return Response("Ok") return Response("Ok")
...@@ -6,8 +6,7 @@ import uuid ...@@ -6,8 +6,7 @@ import uuid
import logging import logging
import random import random
from functools import reduce from functools import reduce
from collections import OrderedDict, defaultdict from collections import OrderedDict
from django.core.cache import cache
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -32,7 +31,7 @@ def default_cluster(): ...@@ -32,7 +31,7 @@ def default_cluster():
def default_node(): def default_node():
try: try:
from .node import Node from .node import Node
root = Node.root() root = Node.org_root()
return root return root
except: except:
return None return None
...@@ -103,33 +102,11 @@ class NodesRelationMixin: ...@@ -103,33 +102,11 @@ class NodesRelationMixin:
id = "" id = ""
_all_nodes_keys = None _all_nodes_keys = None
@classmethod
def get_all_nodes_keys(cls):
"""
:return: {asset.id: [node.key, ]}
"""
from .node import Node
cache_key = cls.ALL_ASSET_NODES_CACHE_KEY
cached = cache.get(cache_key)
if cached:
return cached
assets = Asset.objects.all().only('id').prefetch_related(
models.Prefetch('nodes', queryset=Node.objects.all().only('key'))
)
assets_nodes_keys = {}
for asset in assets:
assets_nodes_keys[asset.id] = [n.key for n in asset.nodes.all()]
cache.set(cache_key, assets_nodes_keys, cls.CACHE_TIME)
return assets_nodes_keys
@classmethod
def expire_all_nodes_keys_cache(cls):
cache_key = cls.ALL_ASSET_NODES_CACHE_KEY
cache.delete(cache_key)
def get_nodes(self): def get_nodes(self):
from .node import Node from .node import Node
nodes = self.nodes.all() or [Node.root()] nodes = self.nodes.all()
if not nodes:
nodes = Node.objects.filter(id=Node.org_root().id)
return nodes return nodes
def get_all_nodes(self, flat=False): def get_all_nodes(self, flat=False):
......
...@@ -24,40 +24,34 @@ class NodeQuerySet(models.QuerySet): ...@@ -24,40 +24,34 @@ class NodeQuerySet(models.QuerySet):
class TreeMixin: class TreeMixin:
time_tree_updated = None tree_created_time = None
time_tree_updated_cache_key = 'NODE_TREE_CREATED_AT' tree_updated_time_cache_key = 'NODE_TREE_CREATED_AT'
tree_cache_time = 3600 tree_update_time_cache_time = 3600
_tree_service = None _tree_service = None
@classmethod @classmethod
def tree(cls): def tree(cls):
# Todo: 有待优化, 因为每次刷新都会导致其他节点的tree失效 # Todo: 有待优化, 因为每次刷新都会导致其他节点的tree失效 完成
# Todo: ungroup node
# TOdo: 游离的资产,在树上显示的数量不对 # TOdo: 游离的资产,在树上显示的数量不对
# Todo: api key页面有bug # Todo: ungroup node
# Todo: api key页面有bug 完成
from ..utils import TreeService from ..utils import TreeService
cache_updated_time = cls.get_cache_time() tree_updated_time = cache.get(cls.tree_updated_time_cache_key, 0)
if not cls.time_tree_updated or \ if not cls.tree_created_time or \
cache_updated_time != cls.time_tree_updated: tree_updated_time > cls.tree_created_time:
t = TreeService.new() print("New tree")
cls.update_cache_tree(t) tree = TreeService.new()
return t cls.tree_created_time = time.time()
cls._tree_service = tree
return tree
return cls._tree_service return cls._tree_service
@classmethod
def get_cache_time(cls):
return cache.get(cls.time_tree_updated_cache_key)
@classmethod
def update_cache_tree(cls, t):
cls._tree_service = t
now = time.time()
cls.time_tree_updated = now
cache.set(cls.time_tree_updated_cache_key, now, cls.tree_cache_time)
@classmethod @classmethod
def expire_cache_tree(cls): def expire_cache_tree(cls):
cache.delete(cls.time_tree_updated_cache_key) key = cls.tree_updated_time_cache_key
ttl = cls.tree_update_time_cache_time
value = time.time()
cache.set(key, value, ttl)
@classmethod @classmethod
def refresh_tree(cls): def refresh_tree(cls):
...@@ -74,6 +68,20 @@ class FamilyMixin: ...@@ -74,6 +68,20 @@ class FamilyMixin:
__all_children = None __all_children = None
is_node = True is_node = True
@staticmethod
def clean_children_keys(nodes_keys):
nodes_keys = sorted(list(nodes_keys), key=lambda x: (len(x), x))
nodes_keys_clean = []
for key in nodes_keys[::-1]:
found = False
for k in nodes_keys:
if key.startswith(k + ':'):
found = True
break
if not found:
nodes_keys_clean.append(key)
return nodes_keys_clean
@property @property
def children(self): def children(self):
return self.get_children(with_self=False) return self.get_children(with_self=False)
...@@ -108,7 +116,7 @@ class FamilyMixin: ...@@ -108,7 +116,7 @@ class FamilyMixin:
@property @property
def parent(self): def parent(self):
if self.is_root(): if self.is_org_root():
return self return self
parent_key = self.parent_key parent_key = self.parent_key
return Node.objects.get(key=parent_key) return Node.objects.get(key=parent_key)
...@@ -122,10 +130,10 @@ class FamilyMixin: ...@@ -122,10 +130,10 @@ class FamilyMixin:
old_key = self.key old_key = self.key
with transaction.atomic(): with transaction.atomic():
self.key = parent.get_next_child_key() self.key = parent.get_next_child_key()
self.save()
for child in children: for child in children:
child.key = child.key.replace(old_key, self.key, 1) child.key = child.key.replace(old_key, self.key, 1)
child.save() child.save()
self.save()
def get_siblings(self, with_self=False): def get_siblings(self, with_self=False):
key = ':'.join(self.key.split(':')[:-1]) key = ':'.join(self.key.split(':')[:-1])
...@@ -182,21 +190,17 @@ class FullValueMixin: ...@@ -182,21 +190,17 @@ class FullValueMixin:
@property @property
def full_value(self): def full_value(self):
if self.is_root(): if self.is_org_root():
return self.value return self.value
if self._full_value is not None: if self._full_value is not None:
return self._full_value return self._full_value
print("Get full value")
value = self._tree.get_node_full_tag(self.key) value = self._tree.get_node_full_tag(self.key)
return value return value
class NodeAssetsMixin: class NodeAssetsMixin:
_assets_amount_cache_key = '_NODE_ASSETS_AMOUNT_{}'
_assets_cache_key = '_NODE_ASSETS_{}'
_assets_amount = None _assets_amount = None
key = '' key = ''
cache_time = 3600 * 24 * 7
id = None id = None
@property @property
...@@ -210,24 +214,19 @@ class NodeAssetsMixin: ...@@ -210,24 +214,19 @@ class NodeAssetsMixin:
amount = self._tree.assets_amount(self.key) amount = self._tree.assets_amount(self.key)
return amount return amount
# TOdo: 是否依赖tree
def get_all_assets(self): def get_all_assets(self):
from .asset import Asset from .asset import Asset
if self.is_root(): if self.is_org_root():
return Asset.objects.filter(org_id=self.org_id) return Asset.objects.filter(org_id=self.org_id)
assets_ids = self._tree.all_assets(self.key) pattern = '^{0}$|^{0}:'.format(self.key)
return Asset.objects.filter(id__in=assets_ids) return Asset.objects.filter(nodes__key__regex=pattern).distinct()
def assets_ids(self):
assets_ids = self._tree.assets(self.key)
return assets_ids
def get_assets(self): def get_assets(self):
from .asset import Asset from .asset import Asset
if self.is_default_node(): if self.is_org_root():
assets = Asset.objects.filter(Q(nodes__id=self.id) | Q(nodes__isnull=True)) assets = Asset.objects.filter(Q(nodes=self) | Q(nodes__isnull=True))
else: else:
assets = Asset.objects.filter(id=self.assets_ids()) assets = Asset.objects.filter(nodes=self)
return assets.distinct() return assets.distinct()
def get_valid_assets(self): def get_valid_assets(self):
...@@ -236,6 +235,16 @@ class NodeAssetsMixin: ...@@ -236,6 +235,16 @@ class NodeAssetsMixin:
def get_all_valid_assets(self): def get_all_valid_assets(self):
return self.get_all_assets().valid() return self.get_all_assets().valid()
@classmethod
def get_nodes_all_assets(cls, nodes_keys):
from .asset import Asset
nodes_keys = cls.clean_children_keys(nodes_keys)
pattern = set()
for key in nodes_keys:
pattern.add(r'^{0}$|^{0}:'.format(key))
pattern = '|'.join(list(pattern))
return Asset.objects.filter(nodes__key__regex=pattern)
class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixin): class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
...@@ -261,22 +270,13 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi ...@@ -261,22 +270,13 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
return self.id == other.id return self.id == other.id
def __gt__(self, other): def __gt__(self, other):
# if self.is_root() and not other.is_root():
# return False
# elif not self.is_root() and other.is_root():
# return True
self_key = [int(k) for k in self.key.split(':')] self_key = [int(k) for k in self.key.split(':')]
other_key = [int(k) for k in other.key.split(':')] other_key = [int(k) for k in other.key.split(':')]
self_parent_key = self_key[:-1] self_parent_key = self_key[:-1]
other_parent_key = other_key[:-1] other_parent_key = other_key[:-1]
if self_parent_key and other_parent_key and \ if self_parent_key and self_parent_key == other_parent_key:
self_parent_key == other_parent_key:
return self.value > other.value return self.value > other.value
# if len(self_parent_key) < len(other_parent_key):
# return True
# elif len(self_parent_key) > len(other_parent_key):
# return False
return self_key > other_key return self_key > other_key
def __lt__(self, other): def __lt__(self, other):
...@@ -310,7 +310,9 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi ...@@ -310,7 +310,9 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
def create_child(self, value, _id=None): def create_child(self, value, _id=None):
with transaction.atomic(): with transaction.atomic():
child_key = self.get_next_child_key() child_key = self.get_next_child_key()
child = self.__class__.objects.create(id=_id, key=child_key, value=value) child = self.__class__.objects.create(
id=_id, key=child_key, value=value
)
return child return child
@classmethod @classmethod
...@@ -318,37 +320,39 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi ...@@ -318,37 +320,39 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
cls.refresh_tree() cls.refresh_tree()
def is_default_node(self): def is_default_node(self):
return self.is_root() and self.key == '1' return self.key == '1'
def is_root(self): def is_org_root(self):
if self.key.isdigit(): if self.key.isdigit():
return True return True
else: else:
return False return False
@classmethod @classmethod
def create_root_node(cls): def create_org_root_node(cls):
# 如果使用current_org 在set_current_org时会死循环 # 如果使用current_org 在set_current_org时会死循环
_current_org = get_current_org() ori_org = get_current_org()
with transaction.atomic(): with transaction.atomic():
if not _current_org.is_real(): if not ori_org.is_real():
return cls.default_node() return cls.default_node()
set_current_org(Organization.root()) set_current_org(Organization.root())
org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$') org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) or ['1'] org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True)
if not org_nodes_roots_keys:
org_nodes_roots_keys = ['1']
key = max([int(k) for k in org_nodes_roots_keys]) key = max([int(k) for k in org_nodes_roots_keys])
key = str(key + 1) if key != 0 else '2' key = str(key + 1) if key != 0 else '2'
set_current_org(_current_org) set_current_org(ori_org)
root = cls.objects.create(key=key, value=_current_org.name) root = cls.objects.create(key=key, value=ori_org.name)
return root return root
@classmethod @classmethod
def root(cls): def org_root(cls):
root = cls.objects.filter(key__regex=r'^[0-9]+$') root = cls.objects.filter(key__regex=r'^[0-9]+$')
if root: if root:
return root[0] return root[0]
else: else:
return cls.create_root_node() return cls.create_org_root_node()
@classmethod @classmethod
def default_node(cls): def default_node(cls):
...@@ -365,7 +369,7 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi ...@@ -365,7 +369,7 @@ class Node(OrgModelMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixi
'title': name, 'title': name,
'pId': self.parent_key, 'pId': self.parent_key,
'isParent': True, 'isParent': True,
'open': self.is_root(), 'open': self.is_org_root(),
'meta': { 'meta': {
'node': { 'node': {
"id": self.id, "id": self.id,
......
...@@ -148,9 +148,11 @@ class SystemUser(AssetUser): ...@@ -148,9 +148,11 @@ class SystemUser(AssetUser):
return True, None return True, None
def get_all_assets(self): def get_all_assets(self):
from .node import Node
args = [Q(systemuser=self)] args = [Q(systemuser=self)]
pattern = set() pattern = set()
nodes_keys = self.nodes.all().values_list('key', flat=True) nodes_keys = self.nodes.all().values_list('key', flat=True)
nodes_keys = Node.clean_children_keys(nodes_keys)
for key in nodes_keys: for key in nodes_keys:
pattern.add(r'^{0}$|^{0}:'.format(key)) pattern.add(r'^{0}$|^{0}:'.format(key))
pattern = '|'.join(list(pattern)) pattern = '|'.join(list(pattern))
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from collections import defaultdict from collections import defaultdict
from django.db.models.signals import post_save, m2m_changed, pre_delete from django.db.models.signals import (
post_save, m2m_changed, pre_delete, pre_save, pre_init, post_init
)
from django.dispatch import receiver from django.dispatch import receiver
from common.utils import get_logger from common.utils import get_logger
...@@ -30,6 +32,9 @@ def test_asset_conn_on_created(asset): ...@@ -30,6 +32,9 @@ def test_asset_conn_on_created(asset):
@receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier") @receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier")
@on_transaction_commit @on_transaction_commit
def on_asset_created_or_update(sender, instance=None, created=False, **kwargs): def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
"""
当资产创建时,更新硬件信息,更新可连接性
"""
if created: if created:
logger.info("Asset `{}` create signal received".format(instance)) logger.info("Asset `{}` create signal received".format(instance))
...@@ -37,78 +42,81 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs): ...@@ -37,78 +42,81 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
update_asset_hardware_info_on_created(instance) update_asset_hardware_info_on_created(instance)
test_asset_conn_on_created(instance) test_asset_conn_on_created(instance)
# 过期节点资产数量
Node.refresh_nodes()
@receiver(pre_delete, sender=Asset, dispatch_uid="my_unique_identifier") @receiver(pre_delete, sender=Asset, dispatch_uid="my_unique_identifier")
def on_asset_delete(sender, instance=None, **kwargs): def on_asset_delete(sender, instance=None, **kwargs):
# 过期节点资产数量 """
当资产删除时,刷新节点,节点中存在节点和资产的关系
"""
Node.refresh_nodes() Node.refresh_nodes()
@receiver(post_save, sender=SystemUser, dispatch_uid="my_unique_identifier") @receiver(post_save, sender=SystemUser, dispatch_uid="my_unique_identifier")
def on_system_user_update(sender, instance=None, created=True, **kwargs): def on_system_user_update(sender, instance=None, created=True, **kwargs):
"""
当系统用户更新时,可能更新了秘钥,用户名等,这时要自动推送系统用户到资产上,
其实应该当 用户名,密码,秘钥 sudo等更新时再推送,这里偷个懒,
这里直接取了 instance.assets 因为nodes和系统用户发生变化时,会自动将nodes下的资产
关联到上面
"""
if instance and not created: if instance and not created:
logger.info("System user `{}` update signal received".format(instance)) logger.info("System user `{}` update signal received".format(instance))
assets = instance.assets.all() assets = instance.assets.all().valid()
push_system_user_to_assets.delay(instance, assets) push_system_user_to_assets.delay(instance, assets)
# @receiver(m2m_changed, sender=SystemUser.nodes.through) @receiver(m2m_changed, sender=SystemUser.assets.through, dispatch_uid="my_unique_identifier")
# def on_system_user_nodes_change(sender, instance=None, **kwargs):
# if instance and kwargs["action"] == "post_add":
# logger.info("System user `{}` nodes update signal received".format(instance))
# assets = set()
# nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
# for node in nodes:
# assets.update(set(node.get_all_assets()))
# instance.assets.add(*tuple(assets))
#
@receiver(m2m_changed, sender=SystemUser.assets.through)
def on_system_user_assets_change(sender, instance=None, **kwargs): def on_system_user_assets_change(sender, instance=None, **kwargs):
"""
当系统用户和资产关系发生变化时,应该重新推送系统用户到新添加的资产中
"""
if instance and kwargs["action"] == "post_add": if instance and kwargs["action"] == "post_add":
assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
push_system_user_to_assets.delay(instance, assets) push_system_user_to_assets.delay(instance, assets)
@receiver(m2m_changed, sender=Asset.nodes.through) @receiver(m2m_changed, sender=SystemUser.nodes.through, dispatch_uid="my_unique_identifier")
def on_asset_node_changed(sender, instance=None, **kwargs): def on_system_user_nodes_change(sender, instance=None, **kwargs):
logger.debug("Asset nodes change signal received") """
Asset.expire_all_nodes_keys_cache() 当系统用户和节点关系发生变化时,应该将节点关联到新的系统用户上
"""
if instance and kwargs["action"] == "post_add":
logger.info("System user `{}` nodes update signal received".format(instance))
nodes_keys = kwargs['model'].objects.filter(
pk__in=kwargs['pk_set']
).values_list('key', flat=True)
assets = Node.get_nodes_all_assets(nodes_keys)
instance.assets.add(*tuple(assets))
@receiver(m2m_changed, sender=Asset.nodes.through, dispatch_uid="my_unique_identifier")
def on_asset_nodes_changed(sender, instance=None, **kwargs):
"""
当资产的节点发生变化时,或者 当节点的资产关系发生变化时,
节点下新增的资产,添加到节点关联的系统用户中
并刷新节点
"""
if isinstance(instance, Asset): if isinstance(instance, Asset):
# nodes = [] logger.debug("Asset nodes change signal received: {}".format(instance))
# if kwargs['action'] == 'pre_remove': # 节点资产发生变化时,将资产关联到节点关联的系统用户
# nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
if kwargs['action'] == 'post_add': if kwargs['action'] == 'post_add':
nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
system_users_assets = defaultdict(set) system_users_assets = defaultdict(set)
system_users = SystemUser.objects.filter(nodes__in=nodes) system_users = SystemUser.objects.filter(nodes__in=nodes)
for system_user in system_users: for system_user in system_users:
system_users_assets[system_user].update({instance}) system_users_assets[system_user].add(instance)
for system_user, assets in system_users_assets.items(): for system_user, assets in system_users_assets.items():
system_user.assets.add(*tuple(assets)) system_user.assets.add(*tuple(assets))
Node.refresh_nodes()
@receiver(m2m_changed, sender=Asset.nodes.through)
def on_node_assets_changed(sender, instance=None, **kwargs):
if isinstance(instance, Node): if isinstance(instance, Node):
logger.debug("Node assets change signal {} received".format(instance)) logger.debug("Node assets change signal received: {}".format(instance))
# 当节点和资产关系发生改变时,过期资产数量缓存
assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) Node.refresh_nodes()
if kwargs['action'] == 'post_add':
# 重新关联系统用户和资产的关系
system_users = SystemUser.objects.filter(nodes=instance)
for system_user in system_users:
system_user.assets.add(*tuple(assets))
@receiver(post_save, sender=Node) @receiver(post_save, sender=Node)
def on_node_update_or_created(sender, instance=None, created=False, **kwargs): def on_node_update_or_created(sender, instance=None, created=False, **kwargs):
if instance and not created: # 刷新节点
Node.refresh_nodes() Node.refresh_nodes()
@receiver(post_save, sender=AuthBook) @receiver(post_save, sender=AuthBook)
......
...@@ -32,7 +32,7 @@ class AssetListView(PermissionsMixin, TemplateView): ...@@ -32,7 +32,7 @@ class AssetListView(PermissionsMixin, TemplateView):
permission_classes = [IsOrgAdmin] permission_classes = [IsOrgAdmin]
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
Node.root() Node.org_root()
context = { context = {
'app': _('Assets'), 'app': _('Assets'),
'action': _('Asset list'), 'action': _('Asset list'),
...@@ -85,7 +85,7 @@ class AssetCreateView(PermissionsMixin, FormMixin, TemplateView): ...@@ -85,7 +85,7 @@ class AssetCreateView(PermissionsMixin, FormMixin, TemplateView):
if node_id: if node_id:
node = get_object_or_none(Node, id=node_id) node = get_object_or_none(Node, id=node_id)
else: else:
node = Node.root() node = Node.org_root()
form["nodes"].initial = node form["nodes"].initial = node
return form return form
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<script> <script>
var table = null; var table = null;
function initTable() { function initAccessKeyTable() {
var options = { var options = {
ele: $('#access_key_list_table'), ele: $('#access_key_list_table'),
columnDefs: [ columnDefs: [
...@@ -93,7 +93,7 @@ function initTable() { ...@@ -93,7 +93,7 @@ function initTable() {
$(document).ready(function () { $(document).ready(function () {
}).on("show.bs.modal", "#access_key_modal", function () { }).on("show.bs.modal", "#access_key_modal", function () {
if (!table) { if (!table) {
initTable() initAccessKeyTable()
} }
}).on("click", "#create-btn", function () { }).on("click", "#create-btn", function () {
var url = "{% url "api-auth:access-key-list" %}"; var url = "{% url "api-auth:access-key-list" %}";
......
...@@ -16,7 +16,7 @@ def on_org_create_or_update(sender, instance=None, created=False, **kwargs): ...@@ -16,7 +16,7 @@ def on_org_create_or_update(sender, instance=None, created=False, **kwargs):
if instance: if instance:
old_org = get_current_org() old_org = get_current_org()
set_current_org(instance) set_current_org(instance)
node_root = Node.root() node_root = Node.org_root()
if node_root.value != instance.name: if node_root.value != instance.name:
node_root.value = instance.name node_root.value = instance.name
node_root.save() node_root.save()
......
...@@ -97,6 +97,7 @@ class AssetPermission(BasePermission): ...@@ -97,6 +97,7 @@ class AssetPermission(BasePermission):
args = [Q(granted_by_permissions=self)] args = [Q(granted_by_permissions=self)]
pattern = set() pattern = set()
nodes_keys = self.nodes.all().values_list('key', flat=True) nodes_keys = self.nodes.all().values_list('key', flat=True)
nodes_keys = Node.clean_children_keys(nodes_keys)
for key in nodes_keys: for key in nodes_keys:
pattern.add(r'^{0}$|^{0}:'.format(key)) pattern.add(r'^{0}$|^{0}:'.format(key))
pattern = '|'.join(list(pattern)) pattern = '|'.join(list(pattern))
......
...@@ -2,24 +2,15 @@ ...@@ -2,24 +2,15 @@
# #
from django.db.models.signals import m2m_changed, post_save, post_delete from django.db.models.signals import m2m_changed, post_save, post_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.db import transaction
from common.utils import get_logger from common.utils import get_logger
from common.decorator import on_transaction_commit
from .models import AssetPermission from .models import AssetPermission
logger = get_logger(__file__) logger = get_logger(__file__)
def on_transaction_commit(func):
"""
如果不调用on_commit, 对象创建时添加多对多字段值失败
"""
def inner(*args, **kwargs):
transaction.on_commit(lambda: func(*args, **kwargs))
return inner
@receiver(post_save, sender=AssetPermission, dispatch_uid="my_unique_identifier") @receiver(post_save, sender=AssetPermission, dispatch_uid="my_unique_identifier")
@on_transaction_commit @on_transaction_commit
def on_permission_created(sender, instance=None, created=False, **kwargs): def on_permission_created(sender, instance=None, created=False, **kwargs):
......
# coding: utf-8 # coding: utf-8
import re
from collections import defaultdict from collections import defaultdict
from functools import reduce from functools import reduce
...@@ -250,6 +249,7 @@ class AssetPermissionUtilV2: ...@@ -250,6 +249,7 @@ class AssetPermissionUtilV2:
return system_users_actions return system_users_actions
def get_permissions_nodes_and_assets(self): def get_permissions_nodes_and_assets(self):
from assets.models import Node
permissions = self.permissions.values_list('assets', 'nodes__key').distinct() permissions = self.permissions.values_list('assets', 'nodes__key').distinct()
nodes_keys = set() nodes_keys = set()
assets_ids = set() assets_ids = set()
...@@ -258,7 +258,7 @@ class AssetPermissionUtilV2: ...@@ -258,7 +258,7 @@ class AssetPermissionUtilV2:
assets_ids.add(asset_id) assets_ids.add(asset_id)
if node_key: if node_key:
nodes_keys.add(node_key) nodes_keys.add(node_key)
nodes_keys = self.clean_nodes_keys(nodes_keys) nodes_keys = Node.clean_children_keys(nodes_keys)
return nodes_keys, assets_ids return nodes_keys, assets_ids
@staticmethod @staticmethod
...@@ -297,20 +297,6 @@ class AssetPermissionUtilV2: ...@@ -297,20 +297,6 @@ class AssetPermissionUtilV2:
queryset = Asset.objects.filter(id__in=assets_ids) queryset = Asset.objects.filter(id__in=assets_ids)
return queryset.valid().distinct() return queryset.valid().distinct()
@staticmethod
def clean_nodes_keys(nodes_keys):
nodes_keys = sorted(list(nodes_keys), key=lambda x: (len(x), x))
nodes_keys_clean = []
for key in nodes_keys[::-1]:
found = False
for k in nodes_keys:
if key.startswith(k + ':'):
found = True
break
if not found:
nodes_keys_clean.append(key)
return nodes_keys_clean
def get_nodes(self): def get_nodes(self):
return [n.identifier for n in self.user_tree.all_nodes_itr()] return [n.identifier for n in self.user_tree.all_nodes_itr()]
...@@ -357,7 +343,7 @@ class ParserNode: ...@@ -357,7 +343,7 @@ class ParserNode:
'title': name, 'title': name,
'pId': node.parent_key, 'pId': node.parent_key,
'isParent': True, 'isParent': True,
'open': node.is_root(), 'open': node.is_org_root(),
'meta': { 'meta': {
'node': { 'node': {
"id": node.id, "id": node.id,
......
...@@ -51,7 +51,8 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView): ...@@ -51,7 +51,8 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
if nodes_id: if nodes_id:
nodes_id = nodes_id.split(",") nodes_id = nodes_id.split(",")
nodes = Node.objects.filter(id__in=nodes_id).exclude(id=Node.root().id) nodes = Node.objects.filter(id__in=nodes_id)\
.exclude(id=Node.org_root().id)
form['nodes'].initial = nodes form['nodes'].initial = nodes
if assets_id: if assets_id:
assets_id = assets_id.split(",") assets_id = assets_id.split(",")
......
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