mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-01-14 12:06:23 +00:00
* [Update] 暂存,优化解决不了问题 * [Update] 待续(小白) * [Update] 修改asset user * [Update] 计划再次更改 * [Update] 修改asset user * [Update] 暂存与喜爱 * [Update] Add id in * [Update] 阶段性完成ops task该做 * [Update] 修改asset user api * [Update] 修改asset user 任务,查看认证等 * [Update] 基本完成asset user改造 * [Update] dynamic user only allow 1 * [Update] 修改asset user task * [Update] 修改node admin user task api * [Update] remove file header license * [Update] 添加sftp root * [Update] 暂存 * [Update] 暂存 * [Update] 修改翻译 * [Update] 修改系统用户改为同名后,用户名改为空 * [Update] 基本完成CAS调研 * [Update] 支持cas server * [Update] 支持cas server * [Update] 添加requirements * [Update] 为方便调试添加mysql ipython到包中 * [Update] 添加huaweiyun翻译 * [Update] 增加下载session 录像 * [Update] 只有第一次通知replay离线的使用方法 * [Update] 暂存一下 * [Bugfix] 获取系统用户信息报错 * [Bugfix] 修改system user info * [Update] 改成清理10天git status * [Update] 修改celery日志保留时间 * [Update]修复部分pip包依赖的版本不兼容问题 (#3672) * [Update] 修复用户更新页面会清空用户public_key的问题 * Fix broken dependencies Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> * [Update] 修改获取系统用户auth info * [Update] Remove log * [Bugfix] 修复sftp home设置的bug * [Update] 授权的系统用户添加sftp root * [Update] 修改系统用户关联的用户 * [Update] 修改placeholder * [Update] 优化获取授权的系统用户 * [Update] 修改tasks * [Update] tree service update * [Update] 暂存 * [Update] 基本完成用户授权树和资产树改造 * [Update] Dashbaord perf * [update] Add huawei cloud sdk requirements * [Updte] 优化dashboard页面 * [Update] system user auth info 添加id * [Update] 修改系统用户serializer * [Update] 优化api * [Update] LDAP Test Util (#3720) * [Update] LDAPTestUtil 1 * [Update] LDAPTestUtil 2 * [Update] LDAPTestUtil 3 * [Update] LDAPTestUtil 4 * [Update] LDAPTestUtil 5 * [Update] LDAPTestUtil 6 * [Update] LDAPTestUtil 7 * [Update] session 已添加is success,并且添加display serializer * [Bugfix] 修复无法删除空节点的bug * [Update] 命令记录分组织显示 * [Update] Session is_success 添加迁移文件 * [Update] 批量命令添加org_id * [Update] 修复一些文案,修改不绑定MFA,不能ssh登录 * [Update] 修改replay api, 返回session信息 * [Update] 解决无效es导致访问命令记录页面失败的问题 * [Update] 拆分profile view * [Update] 修改一个翻译 * [Update] 修改aysnc api框架 * [Update] 命令列表添加risk level * [Update] 完成录像打包下载 * [Update] 更改登陆otp页面 * [Update] 修改command 存储redis_level * [Update] 修改翻译 * [Update] 修改系统用户的用户列表字段 * [Update] 使用新logo和统一Jumpserver为JumpServer * [Update] 优化cloud task * [Update] 统一period task * [Update] 统一period form serializer字段 * [Update] 修改period task * [Update] 修改资产网关信息 * [Update] 用户授权资产树资产信息添加domain * [Update] 修改翻译 * [Update] 测试可连接性 * 1.5.7 bai (#3764) * [Update] 修复index页面Bug;修复测试资产用户可连接性问题; * [Update] 修改测试资产用户可连接 * [Bugfix] 修复backends问题 * [Update] 修改marksafe依赖版本 * [Update] 修改测试资产用户可连接性 * [Update] 修改检测服务器性能时获取percent值 * [Update] 更新依赖boto3=1.12.14 Co-authored-by: Yanzhe Lee <lee.yanzhe@yanzhe.org> Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Co-authored-by: Bai <bugatti_it@163.com>
194 lines
6.1 KiB
Python
194 lines
6.1 KiB
Python
# ~*~ coding: utf-8 ~*~
|
|
#
|
|
from treelib import Tree
|
|
from treelib.exceptions import NodeIDAbsentError
|
|
from collections import defaultdict
|
|
from copy import deepcopy
|
|
|
|
from common.utils import get_logger, timeit, lazyproperty
|
|
from .models import Asset, Node
|
|
|
|
|
|
logger = get_logger(__file__)
|
|
|
|
|
|
class TreeService(Tree):
|
|
tag_sep = ' / '
|
|
|
|
@staticmethod
|
|
@timeit
|
|
def get_nodes_assets_map():
|
|
nodes_assets_map = defaultdict(set)
|
|
asset_node_list = Node.assets.through.objects.values_list(
|
|
'asset', 'node__key'
|
|
)
|
|
for asset_id, key in asset_node_list:
|
|
nodes_assets_map[key].add(asset_id)
|
|
return nodes_assets_map
|
|
|
|
@classmethod
|
|
@timeit
|
|
def new(cls):
|
|
from .models import Node
|
|
all_nodes = list(Node.objects.all().values("key", "value"))
|
|
all_nodes.sort(key=lambda x: len(x["key"].split(":")))
|
|
tree = cls()
|
|
tree.create_node(tag='', identifier='', data={})
|
|
for node in all_nodes:
|
|
key = node["key"]
|
|
value = node["value"]
|
|
parent_key = ":".join(key.split(":")[:-1])
|
|
tree.safe_create_node(
|
|
tag=value, identifier=key,
|
|
parent=parent_key,
|
|
)
|
|
tree.init_assets()
|
|
return tree
|
|
|
|
def init_assets(self):
|
|
node_assets_map = self.get_nodes_assets_map()
|
|
for node in self.all_nodes_itr():
|
|
key = node.identifier
|
|
assets = node_assets_map.get(key, set())
|
|
data = {"assets": assets, "all_assets": None}
|
|
node.data = data
|
|
|
|
def safe_create_node(self, **kwargs):
|
|
parent = kwargs.get("parent")
|
|
if not self.contains(parent):
|
|
kwargs['parent'] = self.root
|
|
self.create_node(**kwargs)
|
|
|
|
def all_children_ids(self, nid, with_self=True):
|
|
children_ids = self.expand_tree(nid)
|
|
if not with_self:
|
|
next(children_ids)
|
|
return list(children_ids)
|
|
|
|
def all_children(self, nid, with_self=True, deep=False):
|
|
children_ids = self.all_children_ids(nid, with_self=with_self)
|
|
return [self.get_node(i, deep=deep) for i in children_ids]
|
|
|
|
def ancestors_ids(self, nid, with_self=True):
|
|
ancestor_ids = list(self.rsearch(nid))
|
|
ancestor_ids.pop()
|
|
if not with_self:
|
|
ancestor_ids.pop(0)
|
|
return ancestor_ids
|
|
|
|
def ancestors(self, nid, with_self=False, deep=False):
|
|
ancestor_ids = self.ancestors_ids(nid, with_self=with_self)
|
|
return [self.get_node(i, deep=deep) for i in ancestor_ids]
|
|
|
|
def get_node_full_tag(self, nid):
|
|
ancestors = self.ancestors(nid, with_self=True)
|
|
ancestors.reverse()
|
|
return self.tag_sep.join([n.tag for n in ancestors])
|
|
|
|
def get_family(self, nid, deep=False):
|
|
ancestors = self.ancestors(nid, with_self=False, deep=deep)
|
|
children = self.all_children(nid, with_self=False)
|
|
return ancestors + [self[nid]] + children
|
|
|
|
@staticmethod
|
|
def is_parent(child, parent):
|
|
parent_id = child.bpointer
|
|
return parent_id == parent.identifier
|
|
|
|
def root_node(self):
|
|
return self.get_node(self.root)
|
|
|
|
def get_node(self, nid, deep=False):
|
|
node = super().get_node(nid)
|
|
if deep:
|
|
node = self.copy_node(node)
|
|
return node
|
|
|
|
def parent(self, nid, deep=False):
|
|
parent = super().parent(nid)
|
|
if deep:
|
|
parent = self.copy_node(parent)
|
|
return parent
|
|
|
|
@lazyproperty
|
|
def invalid_assets(self):
|
|
assets = Asset.objects.filter(is_active=False).values_list('id', flat=True)
|
|
return assets
|
|
|
|
def set_assets(self, nid, assets):
|
|
node = self.get_node(nid)
|
|
if node.data is None:
|
|
node.data = {}
|
|
node.data["assets"] = assets
|
|
|
|
def assets(self, nid):
|
|
node = self.get_node(nid)
|
|
return node.data.get("assets", set())
|
|
|
|
def valid_assets(self, nid):
|
|
return set(self.assets(nid)) - set(self.invalid_assets)
|
|
|
|
def all_assets(self, nid):
|
|
node = self.get_node(nid)
|
|
if node.data is None:
|
|
node.data = {}
|
|
all_assets = node.data.get("all_assets")
|
|
if all_assets is not None:
|
|
return all_assets
|
|
all_assets = set(self.assets(nid))
|
|
try:
|
|
children = self.children(nid)
|
|
except NodeIDAbsentError:
|
|
children = []
|
|
for child in children:
|
|
all_assets.update(self.all_assets(child.identifier))
|
|
node.data["all_assets"] = all_assets
|
|
return all_assets
|
|
|
|
def all_valid_assets(self, nid):
|
|
return set(self.all_assets(nid)) - set(self.invalid_assets)
|
|
|
|
def assets_amount(self, nid):
|
|
return len(self.all_assets(nid))
|
|
|
|
def valid_assets_amount(self, nid):
|
|
return len(self.all_valid_assets(nid))
|
|
|
|
@staticmethod
|
|
def copy_node(node):
|
|
new_node = deepcopy(node)
|
|
new_node.fpointer = None
|
|
return new_node
|
|
|
|
def safe_add_ancestors(self, node, ancestors):
|
|
# 如果没有祖先节点,那么添加该节点, 父节点是root node
|
|
if len(ancestors) == 0:
|
|
parent = self.root_node()
|
|
else:
|
|
parent = ancestors[0]
|
|
|
|
# 如果当前节点已再树中,则移动当前节点到父节点中
|
|
# 这个是由于 当前节点放到了二级节点中
|
|
if not self.contains(parent.identifier):
|
|
# logger.debug('Add parent: {}'.format(parent.identifier))
|
|
self.safe_add_ancestors(parent, ancestors[1:])
|
|
|
|
if self.contains(node.identifier):
|
|
# msg = 'Move node to parent: {} => {}'.format(
|
|
# node.identifier, parent.identifier
|
|
# )
|
|
# logger.debug(msg)
|
|
self.move_node(node.identifier, parent.identifier)
|
|
else:
|
|
# logger.debug('Add node: {}'.format(node.identifier))
|
|
self.add_node(node, parent)
|
|
#
|
|
# def __getstate__(self):
|
|
# self.mutex = None
|
|
# self.all_nodes_assets_map = {}
|
|
# self.nodes_assets_map = {}
|
|
# return self.__dict__
|
|
|
|
# def __setstate__(self, state):
|
|
# self.__dict__ = state
|