Пример #1
0
 def get_node_granted_status(cls, key, user):
     ancestor_keys = Node.get_node_ancestor_keys(key, with_self=True)
     has_granted = UserGrantedMappingNode.objects.filter(
         key__in=ancestor_keys, user=user).values_list('granted', flat=True)
     if not has_granted:
         return cls.GRANTED_NONE
     if any(list(has_granted)):
         return cls.GRANTED_DIRECT
     return cls.GRANTED_INDIRECT
Пример #2
0
def on_asset_nodes_add(instance, action, reverse, pk_set, **kwargs):
    """
    本操作共访问 4 次数据库

    当资产的节点发生变化时,或者 当节点的资产关系发生变化时,
    节点下新增的资产,添加到节点关联的系统用户中
    """
    if action != POST_ADD:
        return
    logger.debug("Assets node add signal recv: {}".format(action))
    if reverse:
        nodes = [instance.key]
        asset_ids = pk_set
    else:
        nodes = Node.objects.filter(pk__in=pk_set).values_list('key', flat=True)
        asset_ids = [instance.id]

    # 节点资产发生变化时,将资产关联到节点及祖先节点关联的系统用户, 只关注新增的
    nodes_ancestors_keys = set()
    for node in nodes:
        nodes_ancestors_keys.update(Node.get_node_ancestor_keys(node, with_self=True))

    # 查询所有祖先节点关联的系统用户,都是要跟资产建立关系的
    system_user_ids = SystemUser.objects.filter(
        nodes__key__in=nodes_ancestors_keys
    ).distinct().values_list('id', flat=True)

    # 查询所有已存在的关系
    m2m_model = SystemUser.assets.through
    exist = set(m2m_model.objects.filter(
        systemuser_id__in=system_user_ids, asset_id__in=asset_ids
    ).values_list('systemuser_id', 'asset_id'))
    # TODO 优化
    to_create = []
    for system_user_id in system_user_ids:
        asset_ids_to_push = []
        for asset_id in asset_ids:
            if (system_user_id, asset_id) in exist:
                continue
            asset_ids_to_push.append(asset_id)
            to_create.append(m2m_model(
                systemuser_id=system_user_id,
                asset_id=asset_id,
                org_id=instance.org_id
            ))
        if asset_ids_to_push:
            push_system_user_to_assets.delay(system_user_id, asset_ids_to_push)
    m2m_model.objects.bulk_create(to_create)
Пример #3
0
    def update_nodes_asset_amount(cls, node_keys, asset_pk, operator):
        """
        一个资产与多个节点关系变化时,更新计数

        :param node_keys: 节点 id 的集合
        :param asset_pk: 资产 id
        :param operator: 操作
        """

        # 所有相关节点的祖先节点,组成一棵局部树
        ancestor_keys = set()
        for key in node_keys:
            ancestor_keys.update(Node.get_node_ancestor_keys(key))

        # 相关节点可能是其他相关节点的祖先节点,如果是从相关节点里干掉
        node_keys -= ancestor_keys

        to_update_keys = []
        for key in node_keys:
            # 遍历相关节点,处理它及其祖先节点
            # 查询该节点是否包含待处理资产
            exists = cls._is_asset_exists_in_node(asset_pk, key)
            parent_key = compute_parent_key(key)

            if exists:
                # 如果资产在该节点,那么他及其祖先节点都不用处理
                cls._remove_ancestor_keys(parent_key, ancestor_keys)
                continue
            else:
                # 不存在,要更新本节点
                to_update_keys.append(key)
                # 这里判断 `parent_key` 不能是空,防止数据错误导致的死循环
                # 判断是否在集合里,来区分是否已被处理过
                while parent_key and parent_key in ancestor_keys:
                    exists = cls._is_asset_exists_in_node(asset_pk, parent_key)
                    if exists:
                        cls._remove_ancestor_keys(parent_key, ancestor_keys)
                        break
                    else:
                        to_update_keys.append(parent_key)
                        ancestor_keys.remove(parent_key)
                        parent_key = compute_parent_key(parent_key)

        Node.objects.filter(key__in=to_update_keys).update(
            assets_amount=operator(F('assets_amount'), 1))
Пример #4
0
    def filter_asset(self, queryset):
        is_query_all = self.get_query_param('all', True)
        asset_id = self.get_query_param('asset_id')
        hostname = self.get_query_param('hostname')
        ip = self.get_query_param('ip')

        if asset_id:
            assets = Asset.objects.filter(pk=asset_id)
        elif hostname:
            assets = Asset.objects.filter(hostname=hostname)
        elif ip:
            assets = Asset.objects.filter(ip=ip)
        else:
            return queryset
        if not assets:
            return queryset.none()
        asset = assets.get()

        if not is_query_all:
            queryset = queryset.filter(assets=asset)
            return queryset
        inherit_all_nodekeys = set()
        inherit_nodekeys = asset.nodes.values_list('key', flat=True)

        for key in inherit_nodekeys:
            ancestor_keys = Node.get_node_ancestor_keys(key, with_self=True)
            inherit_all_nodekeys.update(ancestor_keys)

        inherit_all_nodeids = Node.objects.filter(
            key__in=inherit_all_nodekeys).values_list('id', flat=True)
        inherit_all_nodeids = list(inherit_all_nodeids)

        qs1 = queryset.filter(assets=asset).distinct()
        qs2 = queryset.filter(nodes__id__in=inherit_all_nodeids).distinct()

        qs = UnionQuerySet(qs1, qs2)
        return qs