forked from jumpserver/jumpserver
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstack.py
More file actions
137 lines (120 loc) · 5.1 KB
/
stack.py
File metadata and controls
137 lines (120 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# -*- coding: utf-8 -*-
#
from collections import defaultdict
from common.struct import Stack
from common.utils import timeit
from assets.utils import NodeUtil
class PermStackUtilMixin:
def __init__(self, debug=False):
self.stack = None
self._nodes = {}
self._debug = debug
@staticmethod
def sorted_by(node_dict):
return [int(i) for i in node_dict['key'].split(':')]
@staticmethod
def is_children(item1, item2):
key1 = item1["key"]
key2 = item2["key"]
return key2.startswith(key1 + ':') and (
len(key2.split(':')) - len(key1.split(':'))
) == 1
def debug(self, msg):
self._debug and print(msg)
class PermSystemUserNodeUtil(PermStackUtilMixin):
"""
self._nodes: {node.key: {system_user.id: actions,}}
"""
@timeit
def get_nodes_family_and_system_users(self, nodes_with_system_users):
"""
返回所有nodes_with_system_users中的node的家族节点的信息,
并子会继承祖先的系统用户和actions信息
:param nodes_with_system_users:
{node.key: {system_user.id: actions,}, }
:return:
{node.key: {system_user.id: actions,}, }
"""
node_util = NodeUtil()
_nodes_keys = nodes_with_system_users.keys()
family_keys = node_util.get_some_nodes_family_keys_by_keys(_nodes_keys)
nodes_items = []
for i in family_keys:
system_users = nodes_with_system_users.get(i, defaultdict(int))
item = {"key": i, "system_users": system_users}
nodes_items.append(item)
# 按照父子关系排序
nodes_items.sort(key=self.sorted_by)
nodes_items.append({"key": "", "system_users": defaultdict(int)})
self.stack = Stack()
for item in nodes_items:
self.debug("准备: {} 栈顶: {}".format(
item['key'], self.stack.top["key"] if self.stack.top else None)
)
# 入栈之前检查,该节点是不是栈顶节点的子节点
# 如果不是,则栈顶出栈
while self.stack.top and not self.is_children(self.stack.top, item):
# 出栈
self.pop_from_stack_system_users()
# 入栈
self.push_to_stack_system_users(item)
# 出栈最后一个
self.debug("剩余: {}".format(', '.join([n["key"] for n in self.stack])))
return self._nodes
def push_to_stack_system_users(self, item):
"""
:param item:
{"key": node.key, "system_users": {system_user.id: actions,},}
"""
if not self.stack.is_empty():
item_system_users = item["system_users"]
for system_user, action in self.stack.top["system_users"].items():
# 更新栈顶的系统用户和action到将要入栈的item中
item_system_users[system_user] |= action
item["system_users"] = item_system_users
self.debug("入栈: {}".format(item['key']))
self.stack.push(item)
# 出栈
def pop_from_stack_system_users(self):
_node = self.stack.pop()
self._nodes[_node["key"]] = _node["system_users"]
self.debug("出栈: {} 栈顶: {}".format(_node['key'], self.stack.top['key'] if self.stack.top else None))
class PermAssetsAmountUtil(PermStackUtilMixin):
def push_to_stack_nodes_amount(self, item):
self.debug("入栈: {}".format(item['key']))
self.stack.push(item)
def pop_from_stack_nodes_amount(self):
_node = self.stack.pop()
self.debug("出栈: {} 栈顶: {}".format(
_node['key'], self.stack.top['key'] if self.stack.top else None)
)
_node["all_assets"] = _node["all_assets"] | _node["assets"]
_node["assets_amount"] = len(_node["all_assets"])
self._nodes[_node.pop("key")] = _node
if not self.stack.top:
return
self.stack.top["all_assets"]\
.update(_node["all_assets"] | _node["assets"])
def compute_nodes_assets_amount(self, nodes_with_assets):
self.stack = Stack()
nodes_items = []
for key, values in nodes_with_assets.items():
nodes_items.append({
"key": key, "assets": values["assets"],
"all_assets": values["all_assets"], "assets_amount": 0
})
nodes_items.sort(key=self.sorted_by)
nodes_items.append({"key": "", "assets": set(), "all_assets": set(), "assets_amount": 0})
self.stack = Stack()
for item in nodes_items:
self.debug("准备: {} 栈顶: {}".format(
item['key'], self.stack.top["key"] if self.stack.top else None)
)
# 入栈之前检查,该节点是不是栈顶节点的子节点
# 如果不是,则栈顶出栈
while self.stack.top and not self.is_children(self.stack.top, item):
self.pop_from_stack_nodes_amount()
self.push_to_stack_nodes_amount(item)
# 出栈最后一个
self.debug("剩余: {}".format(', '.join([n["key"] for n in self.stack])))
return self._nodes