[Update] 修改一些bug

pull/3243/head
ibuler 2019-09-19 17:27:49 +08:00
parent b7021b5ecb
commit 847e37e641
14 changed files with 105 additions and 75 deletions

View File

@ -10,7 +10,7 @@ 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 common.utils import get_logger, timeit
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
@ -298,14 +298,15 @@ class NodeAssetsMixin:
return self.get_all_assets().valid() return self.get_all_assets().valid()
@classmethod @classmethod
@timeit
def get_nodes_all_assets(cls, nodes_keys): def get_nodes_all_assets(cls, nodes_keys):
from .asset import Asset from .asset import Asset
nodes_keys = cls.clean_children_keys(nodes_keys) nodes_keys = cls.clean_children_keys(nodes_keys)
pattern = set() assets_ids = set()
for key in nodes_keys: for key in nodes_keys:
pattern.add(r'^{0}$|^{0}:'.format(key)) node_assets_ids = cls.tree().all_assets(key)
pattern = '|'.join(list(pattern)) assets_ids.update(set(node_assets_ids))
return Asset.objects.filter(nodes__key__regex=pattern) return Asset.objects.filter(id__in=assets_ids)
class SomeNodesMixin: class SomeNodesMixin:

View File

@ -7,13 +7,14 @@ from django.db.models.signals import (
from django.db.models.aggregates import Count from django.db.models.aggregates import Count
from django.dispatch import receiver from django.dispatch import receiver
from common.utils import get_logger from common.utils import get_logger, timeit
from common.decorator import on_transaction_commit from common.decorator import on_transaction_commit
from .models import Asset, SystemUser, Node from .models import Asset, SystemUser, Node
from .tasks import ( from .tasks import (
update_assets_hardware_info_util, update_assets_hardware_info_util,
test_asset_connectivity_util, test_asset_connectivity_util,
push_system_user_to_assets push_system_user_to_assets,
add_nodes_assets_to_system_users
) )
@ -99,7 +100,7 @@ def on_system_user_nodes_change(sender, instance=None, action=None, model=None,
""" """
if action != "post_add": if action != "post_add":
return return
logger.info("System user `{}` nodes update signal recv".format(instance)) logger.info("System user nodes update signal recv: {}".format(instance))
queryset = model.objects.filter(pk__in=pk_set) queryset = model.objects.filter(pk__in=pk_set)
if model == Node: if model == Node:
@ -108,9 +109,7 @@ def on_system_user_nodes_change(sender, instance=None, action=None, model=None,
else: else:
nodes_keys = [instance.key] nodes_keys = [instance.key]
system_users = queryset system_users = queryset
assets = Node.get_nodes_all_assets(nodes_keys).values_list('id', flat=True) add_nodes_assets_to_system_users.delay(nodes_keys, system_users)
for system_user in system_users:
system_user.assets.add(*tuple(assets))
@receiver(m2m_changed, sender=Asset.nodes.through) @receiver(m2m_changed, sender=Asset.nodes.through)

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .utils import * from .utils import *
from .common import *
from .admin_user_connectivity import * from .admin_user_connectivity import *
from .asset_connectivity import * from .asset_connectivity import *
from .asset_user_connectivity import * from .asset_user_connectivity import *

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
#
from celery import shared_task
__all__ = ['add_nodes_assets_to_system_users']
@shared_task
def add_nodes_assets_to_system_users(nodes_keys, system_users):
from ..models import Node
assets = Node.get_nodes_all_assets(nodes_keys).values_list('id', flat=True)
for system_user in system_users:
system_user.assets.add(*tuple(assets))

View File

@ -24,7 +24,7 @@
var treeUrl = "{% url 'api-perms:my-nodes-children-as-tree' %}?&cache_policy=1"; var treeUrl = "{% url 'api-perms:my-nodes-children-as-tree' %}?&cache_policy=1";
var assetTableUrl = "{% url 'api-perms:my-assets' %}?cache_policy=1"; var assetTableUrl = "{% url 'api-perms:my-assets' %}?cache_policy=1";
var selectUrl = '{% url "api-perms:my-node-assets" node_id=DEFAULT_PK %}?cache_policy=1&all=1'; var selectUrl = '{% url "api-perms:my-node-assets" node_id=DEFAULT_PK %}?cache_policy=1&all=1';
var systemUsersUrl = "{% url 'api-perms:my-asset-system-users' asset_id=DEFAULT_PK %}"; var systemUsersUrl = "{% url 'api-perms:my-asset-system-users' asset_id=DEFAULT_PK %}?cache_policy=1";
var showAssetHref = false; // Need input default true var showAssetHref = false; // Need input default true
var actions = { var actions = {
targets: 4, createdCell: function (td, cellData) { targets: 4, createdCell: function (td, cellData) {

View File

@ -213,3 +213,16 @@ def dict_get_any(d, keys):
if value: if value:
return value return value
return None return None
class lazyproperty:
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
return value

View File

@ -180,6 +180,7 @@ class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
users = serializer.validated_data.get('users') users = serializer.validated_data.get('users')
if users: if users:
perm.users.remove(*tuple(users)) perm.users.remove(*tuple(users))
perm.save()
return Response({"msg": "ok"}) return Response({"msg": "ok"})
else: else:
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
@ -197,6 +198,7 @@ class AssetPermissionAddUserApi(RetrieveUpdateAPIView):
users = serializer.validated_data.get('users') users = serializer.validated_data.get('users')
if users: if users:
perm.users.add(*tuple(users)) perm.users.add(*tuple(users))
perm.save()
return Response({"msg": "ok"}) return Response({"msg": "ok"})
else: else:
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
@ -217,6 +219,7 @@ class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView):
assets = serializer.validated_data.get('assets') assets = serializer.validated_data.get('assets')
if assets: if assets:
perm.assets.remove(*tuple(assets)) perm.assets.remove(*tuple(assets))
perm.save()
return Response({"msg": "ok"}) return Response({"msg": "ok"})
else: else:
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
@ -234,6 +237,7 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
assets = serializer.validated_data.get('assets') assets = serializer.validated_data.get('assets')
if assets: if assets:
perm.assets.add(*tuple(assets)) perm.assets.add(*tuple(assets))
perm.save()
return Response({"msg": "ok"}) return Response({"msg": "ok"})
else: else:
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})

View File

@ -51,8 +51,7 @@ class GetUserAssetPermissionActionsApi(UserAssetPermissionMixin,
asset = get_object_or_404(Asset, id=asset_id) asset = get_object_or_404(Asset, id=asset_id)
system_user = get_object_or_404(SystemUser, id=system_id) system_user = get_object_or_404(SystemUser, id=system_id)
system_users_actions = self.util.get_asset_system_users_with_actions( system_users_actions = self.util.get_asset_system_users_with_actions(asset)
asset)
actions = system_users_actions.get(system_user) actions = system_users_actions.get(system_user)
return {"actions": actions} return {"actions": actions}
@ -103,8 +102,7 @@ class UserGrantedAssetSystemUsersApi(UserAssetPermissionMixin, ListAPIView):
def get_queryset(self): def get_queryset(self):
asset_id = self.kwargs.get('asset_id') asset_id = self.kwargs.get('asset_id')
asset = get_object_or_404(Asset, id=asset_id) asset = get_object_or_404(Asset, id=asset_id)
system_users_with_actions = self.util.get_asset_system_users_with_actions( system_users_with_actions = self.util.get_asset_system_users_with_actions(asset)
asset)
system_users = [] system_users = []
for system_user, actions in system_users_with_actions.items(): for system_user, actions in system_users_with_actions.items():
system_user.actions = actions system_user.actions = actions

View File

@ -1,23 +1,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from common.utils import lazyproperty
from common.tree import TreeNodeSerializer
from ..mixin import UserPermissionMixin from ..mixin import UserPermissionMixin
from ...utils import AssetPermissionUtilV2, ParserNode from ...utils import AssetPermissionUtilV2, ParserNode
from ...hands import Node, Asset from ...hands import Node, Asset
from common.tree import TreeNodeSerializer
class UserAssetPermissionMixin(UserPermissionMixin): class UserAssetPermissionMixin(UserPermissionMixin):
util = None util = None
tree = None
def initial(self, *args, **kwargs): @lazyproperty
super().initial(*args, *kwargs) def util(self):
cache_policy = self.request.query_params.get('cache_policy', '0') cache_policy = self.request.query_params.get('cache_policy', '0')
system_user_id = self.request.query_params.get("system_user") system_user_id = self.request.query_params.get("system_user")
self.util = AssetPermissionUtilV2(self.obj, cache_policy=cache_policy) util = AssetPermissionUtilV2(self.obj, cache_policy=cache_policy)
if system_user_id: if system_user_id:
self.util.filter_permissions(system_users=system_user_id) util.filter_permissions(system_users=system_user_id)
self.tree = self.util.get_user_tree() return util
@lazyproperty
def tree(self):
return self.util.get_user_tree()
class UserNodeTreeMixin: class UserNodeTreeMixin:

View File

@ -19,18 +19,6 @@ permission_m2m_senders = (
) )
@on_transaction_commit
def on_permission_m2m_change(sender, action='', **kwargs):
if not action.startswith('post'):
return
logger.debug('Asset permission m2m changed, refresh user tree cache')
AssetPermissionUtilV2.expire_all_user_tree_cache()
for sender in permission_m2m_senders:
m2m_changed.connect(on_permission_m2m_change, sender=sender)
@receiver([post_save, post_delete], sender=AssetPermission) @receiver([post_save, post_delete], sender=AssetPermission)
@on_transaction_commit @on_transaction_commit
def on_permission_change(sender, action='', **kwargs): def on_permission_change(sender, action='', **kwargs):

View File

@ -1,7 +1,7 @@
# coding: utf-8 # coding: utf-8
import time
import pickle import pickle
import threading
from collections import defaultdict from collections import defaultdict
from functools import reduce from functools import reduce
from hashlib import md5 from hashlib import md5
@ -12,7 +12,7 @@ from django.db.models import Q
from django.conf import settings from django.conf import settings
from orgs.utils import set_to_root_org from orgs.utils import set_to_root_org
from common.utils import get_logger, timeit from common.utils import get_logger, timeit, lazyproperty
from common.tree import TreeNode from common.tree import TreeNode
from assets.utils import TreeService from assets.utils import TreeService
from ..models import AssetPermission from ..models import AssetPermission
@ -131,18 +131,19 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
self.cache_policy = cache_policy self.cache_policy = cache_policy
self.obj_id = str(obj.id) if obj else None self.obj_id = str(obj.id) if obj else None
self._permissions = None self._permissions = None
self._permissions_id = None # 标记_permission的唯一值
self._filter_id = 'None' # 当通过filter更改 permission是标记 self._filter_id = 'None' # 当通过filter更改 permission是标记
self.change_org_if_need() self.change_org_if_need()
self._user_tree = None self._user_tree = None
self._user_tree_filter_id = 'None' self._user_tree_filter_id = 'None'
self.full_tree = Node.tree()
self.mutex = threading.Lock()
@staticmethod @staticmethod
def change_org_if_need(): def change_org_if_need():
set_to_root_org() set_to_root_org()
@lazyproperty
def full_tree(self):
return Node.tree()
@property @property
def permissions(self): def permissions(self):
if self._permissions: if self._permissions:
@ -161,7 +162,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
self._permissions = self.permissions.filter(**filters) self._permissions = self.permissions.filter(**filters)
self._filter_id = md5(filters_json.encode()).hexdigest() self._filter_id = md5(filters_json.encode()).hexdigest()
@property @lazyproperty
def user_tree(self): def user_tree(self):
return self.get_user_tree() return self.get_user_tree()
@ -305,27 +306,26 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
@timeit @timeit
def get_user_tree(self): def get_user_tree(self):
# 使用锁保证多次获取tree的时候顺序执行可以使用缓存 # 使用锁保证多次获取tree的时候顺序执行可以使用缓存
with self.mutex: user_tree = self.get_user_tree_from_local()
user_tree = self.get_user_tree_from_local() if user_tree:
if user_tree: return user_tree
return user_tree user_tree = self.get_user_tree_from_cache_if_need()
user_tree = self.get_user_tree_from_cache_if_need() if user_tree:
if user_tree:
self.set_user_tree_to_local(user_tree)
return user_tree
user_tree = TreeService()
full_tree_root = self.full_tree.root_node()
user_tree.create_node(
tag=full_tree_root.tag,
identifier=full_tree_root.identifier
)
self.add_direct_nodes_to_user_tree(user_tree)
self.add_single_assets_node_to_user_tree(user_tree)
self.parse_user_tree_to_full_tree(user_tree)
self.add_empty_node_if_need(user_tree)
self.set_user_tree_to_cache_if_need(user_tree)
self.set_user_tree_to_local(user_tree) self.set_user_tree_to_local(user_tree)
return user_tree return user_tree
user_tree = TreeService()
full_tree_root = self.full_tree.root_node()
user_tree.create_node(
tag=full_tree_root.tag,
identifier=full_tree_root.identifier
)
self.add_direct_nodes_to_user_tree(user_tree)
self.add_single_assets_node_to_user_tree(user_tree)
self.parse_user_tree_to_full_tree(user_tree)
self.add_empty_node_if_need(user_tree)
self.set_user_tree_to_cache_if_need(user_tree)
self.set_user_tree_to_local(user_tree)
return user_tree
# Todo: 是否可以获取多个资产的系统用户 # Todo: 是否可以获取多个资产的系统用户
def get_asset_system_users_with_actions(self, asset): def get_asset_system_users_with_actions(self, asset):

View File

@ -72,16 +72,10 @@ function initTable() {
$(td).html(cellData); $(td).html(cellData);
}}, }},
{targets: 3, createdCell: function (td, cellData) { {targets: 3, createdCell: function (td, cellData) {
function success(systemUsers) { var innerHtml = '<a class="btn-show-system-users" data-aid="99999999"> {% trans "Show" %} </a>'
var users = []; .replace('99999999', cellData);
$.each(systemUsers, function (id, data) { $(td).html(innerHtml);
var name = htmlEscape(data.name);
users.push(name);
});
$(td).html(users.join(','))
}
$(td).html("{% trans 'Loading' %}");
getGrantedAssetSystemUsers(cellData, success)
}}, }},
], ],
ajax_url: assetTableUrl, ajax_url: assetTableUrl,
@ -185,5 +179,19 @@ $(document).ready(function () {
var val = $(this).text(); var val = $(this).text();
$("#user_assets_table_filter input").val(val); $("#user_assets_table_filter input").val(val);
assetTable.search(val).draw(); assetTable.search(val).draw();
}) }).on('click', '.btn-show-system-users', function () {
var $this = $(this);
var assetId = $this.data('aid');
function success(systemUsers) {
var users = [];
$.each(systemUsers, function (id, data) {
var name = htmlEscape(data.name);
users.push(name);
});
$this.parent().html(users.join(','))
}
getGrantedAssetSystemUsers(assetId, success)
})
</script> </script>

View File

@ -33,9 +33,9 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var assetTableUrl = "{% url 'api-perms:user-assets' pk=object.id %}?cache_policy=1"; var assetTableUrl = "{% url 'api-perms:user-assets' pk=object.id %}?cache_policy=1";
var selectUrl = '{% url "api-perms:user-node-assets" pk=object.id node_id=DEFAULT_PK %}?all=1'; var selectUrl = '{% url "api-perms:user-node-assets" pk=object.id node_id=DEFAULT_PK %}?cache_policy=1&all=1';
var treeUrl = "{% url 'api-perms:user-nodes-children-as-tree' pk=object.id %}?cache_policy=1"; var treeUrl = "{% url 'api-perms:user-nodes-children-as-tree' pk=object.id %}?cache_policy=1";
var systemUsersUrl = "{% url 'api-perms:user-asset-system-users' pk=object.id asset_id=DEFAULT_PK %}"; var systemUsersUrl = "{% url 'api-perms:user-asset-system-users' pk=object.id asset_id=DEFAULT_PK %}?cache_policy=1";
$(document).ready(function () { $(document).ready(function () {
initTree(); initTree();

View File

@ -34,9 +34,9 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var assetTableUrl = "{% url 'api-perms:user-group-assets' pk=object.id %}?cache_policy=1"; var assetTableUrl = "{% url 'api-perms:user-group-assets' pk=object.id %}?cache_policy=1";
var selectUrl = '{% url "api-perms:user-group-node-assets" pk=object.id node_id=DEFAULT_PK %}?all=1'; var selectUrl = '{% url "api-perms:user-group-node-assets" pk=object.id node_id=DEFAULT_PK %}?&cache_policy=1&all=1';
var treeUrl = "{% url 'api-perms:user-group-nodes-children-as-tree' pk=object.id %}?cache_policy=1"; var treeUrl = "{% url 'api-perms:user-group-nodes-children-as-tree' pk=object.id %}?cache_policy=1";
var systemUsersUrl = "{% url 'api-perms:user-group-asset-system-users' pk=object.id asset_id=DEFAULT_PK %}"; var systemUsersUrl = "{% url 'api-perms:user-group-asset-system-users' pk=object.id asset_id=DEFAULT_PK %}?cache_policy=1";
var showAssetHref = true; // Need input default true var showAssetHref = true; // Need input default true