mirror of https://github.com/jumpserver/jumpserver
Bugfix (#3216)
* [Update] 添加 asset permission默认排序,去掉node permission model * [Update] 修复刷新节点的bugpull/3217/head^2
parent
c1d274028f
commit
9bcc325c1e
|
@ -35,7 +35,7 @@ __all__ = [
|
||||||
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi',
|
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi',
|
||||||
'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
|
'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
|
||||||
'TestNodeConnectiveApi', 'NodeListAsTreeApi',
|
'TestNodeConnectiveApi', 'NodeListAsTreeApi',
|
||||||
'NodeChildrenAsTreeApi', 'RefreshAssetsAmount',
|
'NodeChildrenAsTreeApi', 'RefreshNodesCacheApi',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,9 +282,13 @@ class TestNodeConnectiveApi(APIView):
|
||||||
return Response({"task": task.id})
|
return Response({"task": task.id})
|
||||||
|
|
||||||
|
|
||||||
class RefreshAssetsAmount(APIView):
|
class RefreshNodesCacheApi(APIView):
|
||||||
permission_classes = (IsOrgAdmin,)
|
permission_classes = (IsOrgAdmin,)
|
||||||
model = Node
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
Node.refresh_nodes()
|
||||||
return Response("Ok")
|
return Response("Ok")
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.get(*args, **kwargs)
|
||||||
|
return Response(status=204)
|
||||||
|
|
|
@ -10,12 +10,14 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
from common.utils import get_logger
|
||||||
from orgs.mixins.models import OrgModelMixin, OrgManager
|
from orgs.mixins.models import OrgModelMixin, OrgManager
|
||||||
from orgs.utils import set_current_org, get_current_org, tmp_to_org
|
from orgs.utils import set_current_org, get_current_org, tmp_to_org
|
||||||
from orgs.models import Organization
|
from orgs.models import Organization
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['Node']
|
__all__ = ['Node']
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NodeQuerySet(models.QuerySet):
|
class NodeQuerySet(models.QuerySet):
|
||||||
|
@ -39,6 +41,7 @@ class TreeMixin:
|
||||||
tree_updated_time > cls.tree_created_time:
|
tree_updated_time > cls.tree_created_time:
|
||||||
tree = TreeService.new()
|
tree = TreeService.new()
|
||||||
cls.tree_created_time = time.time()
|
cls.tree_created_time = time.time()
|
||||||
|
cls.refresh_tree(cls.tree_assets_created_time)
|
||||||
cls.tree_assets_created_time = time.time()
|
cls.tree_assets_created_time = time.time()
|
||||||
cls._tree_service = tree
|
cls._tree_service = tree
|
||||||
return tree
|
return tree
|
||||||
|
@ -46,26 +49,41 @@ class TreeMixin:
|
||||||
if not cls.tree_assets_created_time or \
|
if not cls.tree_assets_created_time or \
|
||||||
node_assets_updated_time > cls.tree_assets_created_time:
|
node_assets_updated_time > cls.tree_assets_created_time:
|
||||||
cls._tree_service.init_assets_async()
|
cls._tree_service.init_assets_async()
|
||||||
|
cls.tree_assets_created_time = time.time()
|
||||||
|
cls.refresh_node_assets(cls.tree_assets_created_time)
|
||||||
return cls._tree_service
|
return cls._tree_service
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def refresh_tree(cls):
|
def refresh_tree(cls, t=None):
|
||||||
|
logger.debug("Refresh node tree")
|
||||||
key = cls.tree_updated_time_cache_key
|
key = cls.tree_updated_time_cache_key
|
||||||
ttl = cls.tree_cache_time
|
ttl = cls.tree_cache_time
|
||||||
value = time.time()
|
if not t:
|
||||||
cache.set(key, value, ttl)
|
t = time.time()
|
||||||
|
cache.set(key, t, ttl)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def refresh_node_assets(cls):
|
def refresh_node_assets(cls, t=None):
|
||||||
|
logger.debug("Refresh node tree assets")
|
||||||
key = cls.tree_assets_cache_key
|
key = cls.tree_assets_cache_key
|
||||||
ttl = cls.tree_cache_time
|
ttl = cls.tree_cache_time
|
||||||
value = time.time()
|
if not t:
|
||||||
cache.set(key, value, ttl)
|
t = time.time()
|
||||||
|
cache.set(key, t, ttl)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _tree(self):
|
def _tree(self):
|
||||||
return self.__class__.tree()
|
return self.__class__.tree()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def refresh_user_tree_cache():
|
||||||
|
"""
|
||||||
|
当节点-节点关系,节点-资产关系发生变化时,应该刷新用户授权树缓存
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
from perms.utils.asset_permission import AssetPermissionUtilV2
|
||||||
|
AssetPermissionUtilV2.expire_all_user_tree_cache()
|
||||||
|
|
||||||
|
|
||||||
class FamilyMixin:
|
class FamilyMixin:
|
||||||
__parents = None
|
__parents = None
|
||||||
|
@ -113,11 +131,8 @@ class FamilyMixin:
|
||||||
return self.get_ancestor(with_self=False)
|
return self.get_ancestor(with_self=False)
|
||||||
|
|
||||||
def get_ancestor(self, with_self=False):
|
def get_ancestor(self, with_self=False):
|
||||||
parents = self.parents
|
ancestor_keys = self.get_ancestor_keys(with_self=with_self)
|
||||||
if with_self:
|
return self.__class__.objects.filter(key__in=ancestor_keys)
|
||||||
parents = list(parents)
|
|
||||||
parents.append(self)
|
|
||||||
return parents
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent(self):
|
def parent(self):
|
||||||
|
@ -155,9 +170,10 @@ class FamilyMixin:
|
||||||
children = self.get_all_children()
|
children = self.get_all_children()
|
||||||
return [*tuple(ancestor), self, *tuple(children)]
|
return [*tuple(ancestor), self, *tuple(children)]
|
||||||
|
|
||||||
def get_ancestor_keys(self, with_self=False):
|
@classmethod
|
||||||
|
def get_nodes_ancestor_keys_by_key(cls, key, with_self=False):
|
||||||
parent_keys = []
|
parent_keys = []
|
||||||
key_list = self.key.split(":")
|
key_list = key.split(":")
|
||||||
if not with_self:
|
if not with_self:
|
||||||
key_list.pop()
|
key_list.pop()
|
||||||
for i in range(len(key_list)):
|
for i in range(len(key_list)):
|
||||||
|
@ -165,6 +181,11 @@ class FamilyMixin:
|
||||||
key_list.pop()
|
key_list.pop()
|
||||||
return parent_keys
|
return parent_keys
|
||||||
|
|
||||||
|
def get_ancestor_keys(self, with_self=False):
|
||||||
|
return self.__class__.get_nodes_ancestor_keys_by_key(
|
||||||
|
self.key, with_self=with_self
|
||||||
|
)
|
||||||
|
|
||||||
def is_children(self, other):
|
def is_children(self, other):
|
||||||
pattern = r'^{0}:[0-9]+$'.format(self.key)
|
pattern = r'^{0}:[0-9]+$'.format(self.key)
|
||||||
return re.match(pattern, other.key)
|
return re.match(pattern, other.key)
|
||||||
|
@ -398,24 +419,13 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin
|
||||||
def level(self):
|
def level(self):
|
||||||
return len(self.key.split(':'))
|
return len(self.key.split(':'))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def refresh_user_tree_cache():
|
|
||||||
"""
|
|
||||||
当节点-节点关系,节点-资产关系发生变化时,应该刷新用户授权树缓存
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
from perms.utils.asset_permission import AssetPermissionUtilV2
|
|
||||||
AssetPermissionUtilV2.expire_all_user_tree_cache()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def refresh_nodes(cls):
|
def refresh_nodes(cls):
|
||||||
cls.refresh_tree()
|
cls.refresh_tree()
|
||||||
cls.refresh_user_tree_cache()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def refresh_assets(cls):
|
def refresh_assets(cls):
|
||||||
cls.refresh_node_assets()
|
cls.refresh_node_assets()
|
||||||
cls.refresh_user_tree_cache()
|
|
||||||
|
|
||||||
def as_tree_node(self):
|
def as_tree_node(self):
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
|
|
|
@ -74,7 +74,6 @@ function initNodeTree(options) {
|
||||||
if (options.showAssets) {
|
if (options.showAssets) {
|
||||||
treeUrl = setUrlParam(treeUrl, 'assets', '1')
|
treeUrl = setUrlParam(treeUrl, 'assets', '1')
|
||||||
}
|
}
|
||||||
var asyncTreeUrl = setUrlParam(treeUrl, 'refresh', '0');
|
|
||||||
var setting = {
|
var setting = {
|
||||||
view: {
|
view: {
|
||||||
dblClickExpand: false,
|
dblClickExpand: false,
|
||||||
|
@ -87,7 +86,7 @@ function initNodeTree(options) {
|
||||||
},
|
},
|
||||||
async: {
|
async: {
|
||||||
enable: true,
|
enable: true,
|
||||||
url: asyncTreeUrl,
|
url: treeUrl,
|
||||||
autoParam: ["id=key", "name=n", "level=lv"],
|
autoParam: ["id=key", "name=n", "level=lv"],
|
||||||
type: 'get'
|
type: 'get'
|
||||||
},
|
},
|
||||||
|
@ -115,9 +114,15 @@ function initNodeTree(options) {
|
||||||
$.get(treeUrl, function (data, status) {
|
$.get(treeUrl, function (data, status) {
|
||||||
zTree = $.fn.zTree.init($("#nodeTree"), setting, data);
|
zTree = $.fn.zTree.init($("#nodeTree"), setting, data);
|
||||||
rootNodeAddDom(zTree, function () {
|
rootNodeAddDom(zTree, function () {
|
||||||
treeUrl = setUrlParam(treeUrl, 'refresh', '1');
|
const url = '{% url 'api-assets:refresh-nodes-cache' %}';
|
||||||
initNodeTree(options);
|
requestApi({
|
||||||
treeUrl = setUrlParam(treeUrl, 'refresh', '0');
|
url: url,
|
||||||
|
method: 'GET',
|
||||||
|
flash_message: false,
|
||||||
|
success: function () {
|
||||||
|
initNodeTree(options);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
inited = true;
|
inited = true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,8 +85,8 @@ urlpatterns = [
|
||||||
api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
|
api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
|
||||||
path('nodes/<uuid:pk>/test-connective/',
|
path('nodes/<uuid:pk>/test-connective/',
|
||||||
api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
|
api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
|
||||||
path('nodes/refresh-assets-amount/',
|
|
||||||
api.RefreshAssetsAmount.as_view(), name='refresh-assets-amount'),
|
path('nodes/cache/', api.RefreshNodesCacheApi.as_view(), name='refresh-nodes-cache'),
|
||||||
|
|
||||||
path('gateways/<uuid:pk>/test-connective/',
|
path('gateways/<uuid:pk>/test-connective/',
|
||||||
api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
|
api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
|
||||||
|
|
|
@ -70,7 +70,6 @@ class TreeService(Tree):
|
||||||
@classmethod
|
@classmethod
|
||||||
@timeit
|
@timeit
|
||||||
def new(cls):
|
def new(cls):
|
||||||
print("Call new")
|
|
||||||
from .models import Node
|
from .models import Node
|
||||||
from orgs.utils import tmp_to_root_org
|
from orgs.utils import tmp_to_root_org
|
||||||
|
|
||||||
|
@ -91,17 +90,14 @@ class TreeService(Tree):
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
def init_assets(self):
|
def init_assets(self):
|
||||||
from orgs.utils import get_current_org, set_to_root_org
|
from orgs.utils import tmp_to_root_org
|
||||||
origin_org = get_current_org()
|
self.all_nodes_assets_map = {}
|
||||||
set_to_root_org()
|
with tmp_to_root_org():
|
||||||
queryset = Asset.objects.all().valid().values_list('id', 'nodes__key')
|
queryset = Asset.objects.all().values_list('id', 'nodes__key')
|
||||||
|
for asset_id, key in queryset:
|
||||||
if origin_org:
|
if not key:
|
||||||
origin_org.change_to()
|
continue
|
||||||
for asset_id, key in queryset:
|
self.nodes_assets_map[key].add(asset_id)
|
||||||
if not key:
|
|
||||||
continue
|
|
||||||
self.nodes_assets_map[key].add(asset_id)
|
|
||||||
|
|
||||||
def all_children(self, nid, with_self=True, deep=False):
|
def all_children(self, nid, with_self=True, deep=False):
|
||||||
children_ids = self.expand_tree(nid)
|
children_ids = self.expand_tree(nid)
|
||||||
|
|
Loading…
Reference in New Issue