[Update] 更新api和model方法

pull/1395/head
ibuler 2018-05-31 19:47:57 +08:00
parent 69e5ab438a
commit f8ff223f90
7 changed files with 110 additions and 158 deletions

View File

@ -11,8 +11,7 @@ from django.db.models import Q
from common.mixins import IDInFilterMixin from common.mixins import IDInFilterMixin
from common.utils import get_logger from common.utils import get_logger
from ..hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \ from ..hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser
NodePermissionUtil
from ..models import Asset, SystemUser, AdminUser, Node from ..models import Asset, SystemUser, AdminUser, Node
from .. import serializers from .. import serializers
from ..tasks import update_asset_hardware_info_manual, \ from ..tasks import update_asset_hardware_info_manual, \
@ -22,7 +21,7 @@ from ..utils import LabelFilter
logger = get_logger(__file__) logger = get_logger(__file__)
__all__ = [ __all__ = [
'AssetViewSet', 'UserAssetListView', 'AssetListUpdateApi', 'AssetViewSet', 'AssetListUpdateApi',
'AssetRefreshHardwareApi', 'AssetAdminUserTestApi' 'AssetRefreshHardwareApi', 'AssetAdminUserTestApi'
] ]
@ -71,19 +70,6 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
return queryset return queryset
class UserAssetListView(generics.ListAPIView):
queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer
permission_classes = (IsValidUser,)
def get_queryset(self):
assets_granted = NodePermissionUtil.get_user_assets(self.request.user).keys()
queryset = self.queryset.filter(
id__in=[asset.id for asset in assets_granted]
)
return queryset
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView): class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
""" """
Asset bulk update api Asset bulk update api

View File

@ -14,4 +14,3 @@
from common.mixins import AdminUserRequiredMixin from common.mixins import AdminUserRequiredMixin
from common.permissions import IsAppUser, IsSuperUser, IsValidUser, IsSuperUserOrAppUser from common.permissions import IsAppUser, IsSuperUser, IsValidUser, IsSuperUserOrAppUser
from users.models import User, UserGroup from users.models import User, UserGroup
from perms.utils import NodePermissionUtil

View File

@ -5,6 +5,7 @@
import uuid import uuid
import logging import logging
import random import random
from functools import reduce
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -149,6 +150,15 @@ class Asset(models.Model):
nodes = self.nodes.all() or [Node.root()] nodes = self.nodes.all() or [Node.root()]
return nodes return nodes
def get_all_nodes(self, flat=False):
nodes = []
for node in self.get_nodes_or_cache():
_nodes = node.get_ancestor(with_self=True)
_nodes.append(_nodes)
if flat:
nodes = list(reduce(lambda x, y: set(x) | set(y), nodes))
return nodes
@property @property
def nodes_cache_key(self): def nodes_cache_key(self):
key = "NODES_OF_{}".format(str(self.id)) key = "NODES_OF_{}".format(str(self.id))

View File

@ -28,10 +28,9 @@ class Node(models.Model):
@property @property
def full_value(self): def full_value(self):
ancestor = [a.value for a in self.ancestor] ancestor = [a.value for a in self.get_ancestor(with_self=True)]
if self.is_root(): if self.is_root():
return self.value return self.value
ancestor.append(self.value)
return ' / '.join(ancestor) return ' / '.join(ancestor)
@property @property
@ -55,32 +54,35 @@ class Node(models.Model):
return "{}:{}".format(self.key, mark) return "{}:{}".format(self.key, mark)
def create_child(self, value): def create_child(self, value):
child_key = self.get_next_child_key() with transaction.atomic():
child = self.__class__.objects.create(key=child_key, value=value) child_key = self.get_next_child_key()
return child child = self.__class__.objects.create(key=child_key, value=value)
return child
def get_children(self): def get_children(self, with_self=False):
pattern = r'^{0}$|^{}:[0-9]+$' if with_self else r'^{}:[0-9]+$'
return self.__class__.objects.filter( return self.__class__.objects.filter(
key__regex=r'^{}:[0-9]+$'.format(self.key) key__regex=pattern.format(self.key)
) )
def get_children_with_self(self): def get_all_children(self, with_self=False):
pattern = r'^{0}$|^{0}:' if with_self else r'^{0}'
return self.__class__.objects.filter( return self.__class__.objects.filter(
key__regex=r'^{0}$|^{0}:[0-9]+$'.format(self.key) key__regex=pattern.format(self.key)
) )
def get_all_children(self): def get_sibling(self, with_self=False):
return self.__class__.objects.filter( key = ':'.join(self.key.split(':')[:-1])
key__startswith='{}:'.format(self.key) pattern = r'^{}:[0-9]+$'.format(key)
) sibling = self.__class__.objects.filter(
key__regex=pattern.format(self.key)
def get_all_children_with_self(self):
return self.__class__.objects.filter(
key__regex=r'^{0}$|^{0}:'.format(self.key)
) )
if not with_self:
sibling = sibling.exclude(key=self.key)
return sibling
def get_family(self): def get_family(self):
ancestor = self.ancestor ancestor = self.get_ancestor()
children = self.get_all_children() children = self.get_all_children()
return [*tuple(ancestor), self, *tuple(children)] return [*tuple(ancestor), self, *tuple(children)]
@ -102,7 +104,7 @@ class Node(models.Model):
if self.is_root(): if self.is_root():
assets = Asset.objects.all() assets = Asset.objects.all()
else: else:
nodes = self.get_all_children_with_self() nodes = self.get_all_children(with_self=True)
assets = Asset.objects.filter(nodes__in=nodes).distinct() assets = Asset.objects.filter(nodes__in=nodes).distinct()
return assets return assets
@ -127,24 +129,21 @@ class Node(models.Model):
def parent(self, parent): def parent(self, parent):
self.key = parent.get_next_child_key() self.key = parent.get_next_child_key()
@property def get_ancestor(self, with_self=False):
def ancestor(self):
if self.is_root(): if self.is_root():
ancestor = self.__class__.objects.filter(key='0') ancestor = self.__class__.objects.filter(key='0')
else: return ancestor
_key = self.key.split(':')
ancestor_keys = []
for i in range(len(_key)-1):
_key.pop()
ancestor_keys.append(':'.join(_key))
ancestor = self.__class__.objects.filter(key__in=ancestor_keys)
ancestor = list(ancestor)
return ancestor
@property _key = self.key.split(':')
def ancestor_with_self(self): if not with_self:
ancestor = list(self.ancestor) _key.pop()
ancestor.insert(0, self) ancestor_keys = []
for i in range(len(_key)):
ancestor_keys.append(':'.join(_key))
_key.pop()
ancestor = self.__class__.objects.filter(
key__in=ancestor_keys
).order_by('key')
return ancestor return ancestor
@classmethod @classmethod
@ -153,3 +152,12 @@ class Node(models.Model):
key='0', defaults={"key": '0', 'value': "ROOT"} key='0', defaults={"key": '0', 'value': "ROOT"}
) )
return obj return obj
class Tree:
def __init__(self, root):
self.root = root
self.nodes = []
def add_node(self, node):
pass

View File

@ -23,8 +23,6 @@ urlpatterns = [
api.AssetRefreshHardwareApi.as_view(), name='asset-refresh'), api.AssetRefreshHardwareApi.as_view(), name='asset-refresh'),
url(r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/alive/$', url(r'^v1/assets/(?P<pk>[0-9a-zA-Z\-]{36})/alive/$',
api.AssetAdminUserTestApi.as_view(), name='asset-alive-test'), api.AssetAdminUserTestApi.as_view(), name='asset-alive-test'),
url(r'^v1/assets/user-assets/$',
api.UserAssetListView.as_view(), name='user-asset-list'),
url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
api.ReplaceNodesAdminUserApi.as_view(), name='replace-nodes-admin-user'), api.ReplaceNodesAdminUserApi.as_view(), name='replace-nodes-admin-user'),
url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/auth/$', url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/auth/$',
@ -35,17 +33,26 @@ urlpatterns = [
api.SystemUserPushApi.as_view(), name='system-user-push'), api.SystemUserPushApi.as_view(), name='system-user-push'),
url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$', url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$',
api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'), api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$', api.NodeChildrenApi.as_view(), name='node-children'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$',
api.NodeChildrenApi.as_view(), name='node-children'),
url(r'^v1/nodes/children/$', api.NodeChildrenApi.as_view(), name='node-children-2'), url(r'^v1/nodes/children/$', api.NodeChildrenApi.as_view(), name='node-children-2'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$',
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.NodeAssetsApi.as_view(), name='node-assets'), api.NodeAddChildrenApi.as_view(), name='node-add-children'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/replace/$', api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'), api.NodeAssetsApi.as_view(), name='node-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$',
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'), api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/replace/$',
api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$',
api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$',
api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$',
api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
url(r'^v1/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'), url(r'^v1/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$',
api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
] ]
urlpatterns += router.urls urlpatterns += router.urls

View File

@ -41,11 +41,11 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
asset = get_object_or_404(Asset, pk=asset_id) asset = get_object_or_404(Asset, pk=asset_id)
permissions = set(queryset.filter(assets=asset)) permissions = set(queryset.filter(assets=asset))
for node in asset.nodes.all(): for node in asset.nodes.all():
inherit_nodes.update(set(node.ancestor_with_self)) inherit_nodes.update(set(node.get_ancestor(with_self=True)))
elif node_id: elif node_id:
node = get_object_or_404(Node, pk=node_id) node = get_object_or_404(Node, pk=node_id)
permissions = set(queryset.filter(nodes=node)) permissions = set(queryset.filter(nodes=node))
inherit_nodes = node.ancestor inherit_nodes = node.get_ancestor()
for n in inherit_nodes: for n in inherit_nodes:
_permissions = queryset.filter(nodes=n) _permissions = queryset.filter(nodes=n)

View File

@ -3,12 +3,13 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
import collections import collections
from collections import defaultdict from collections import defaultdict
from django.db.models import Q
from django.utils import timezone from django.utils import timezone
import copy import copy
from common.utils import set_or_append_attr_bulk, get_logger from common.utils import set_or_append_attr_bulk, get_logger
from .models import AssetPermission from .models import AssetPermission
from .hands import Node from .hands import Node, User, UserGroup, Asset, SystemUser
logger = get_logger(__file__) logger = get_logger(__file__)
@ -254,106 +255,47 @@ class AssetPermissionUtil:
return system_users return system_users
# Abandon class AssetPermissionUtilsV2:
class NodePermissionUtil: def __init__(self, obj):
""" self.object = obj
self._permissions = None
""" @staticmethod
def get_user_permissions(user):
groups = user.groups.all()
return AssetPermission.objects.all().valid().filter(
Q(users=user) | Q(user_groups=groups)
)
@staticmethod @staticmethod
def get_user_group_permissions(user_group): def get_user_group_permissions(user_group):
return user_group.nodepermission_set.all() \ return AssetPermission.objects.all().valid().filter(
.filter(is_active=True) \ user_groups=user_group
.filter(date_expired__gt=timezone.now()) )
@staticmethod
def get_asset_permissions(asset):
direct_nodes = asset.get_nodes_or_cache()
return AssetPermission.objects.all().valid().filter(
Q(assets=asset) | Q(nodes=direct_nodes)
)
@staticmethod
def get_node_permissions(node):
return AssetPermission.objects.all().valid().filter(nodes=node)
@staticmethod @staticmethod
def get_system_user_permissions(system_user): def get_system_user_permissions(system_user):
return system_user.nodepermission_set.all() \ return AssetPermission.objects.valid().all().filter(
.filter(is_active=True) \ system_users=system_user
.filter(date_expired__gt=timezone.now()) )
@classmethod @property
def get_user_group_nodes(cls, user_group): def permissions(self):
""" if self._permissions:
获取用户组授权的node和系统用户 return self._permissions
:param user_group: if isinstance(self.object, User):
:return: {"node": set(systemuser1, systemuser2), ..} pass
"""
permissions = cls.get_user_group_permissions(user_group)
nodes_directed = collections.defaultdict(set)
for perm in permissions:
nodes_directed[perm.node].add(perm.system_user)
nodes = copy.deepcopy(nodes_directed)
for node, system_users in nodes_directed.items():
for child in node.get_all_children_with_self():
nodes[child].update(system_users)
return nodes
@classmethod
def get_user_group_nodes_with_assets(cls, user_group):
"""
获取用户组授权的节点和系统用户节点下带有资产
:param user_group:
:return: {"node": {"assets": "", "system_user": ""}, {}}
"""
nodes = cls.get_user_group_nodes(user_group)
nodes_with_assets = dict()
for node, system_users in nodes.items():
nodes_with_assets[node] = {
'assets': node.get_valid_assets(),
'system_users': system_users
}
return nodes_with_assets
@classmethod
def get_user_group_assets(cls, user_group):
assets = collections.defaultdict(set)
permissions = cls.get_user_group_permissions(user_group)
for perm in permissions:
for asset in perm.node.get_all_assets():
assets[asset].add(perm.system_user)
return assets
@classmethod
def get_user_nodes(cls, user):
nodes = collections.defaultdict(set)
groups = user.groups.all()
for group in groups:
group_nodes = cls.get_user_group_nodes(group)
for node, system_users in group_nodes.items():
nodes[node].update(system_users)
return nodes
@classmethod
def get_user_nodes_with_assets(cls, user):
nodes = cls.get_user_nodes(user)
nodes_with_assets = dict()
for node, system_users in nodes.items():
nodes_with_assets[node] = {
'assets': node.get_valid_assets(),
'system_users': system_users
}
return nodes_with_assets
@classmethod
def get_user_assets(cls, user):
assets = collections.defaultdict(set)
nodes_with_assets = cls.get_user_nodes_with_assets(user)
for v in nodes_with_assets.values():
for asset in v['assets']:
assets[asset].update(v['system_users'])
return assets
@classmethod
def get_system_user_assets(cls, system_user):
assets = set()
permissions = cls.get_system_user_permissions(system_user)
for perm in permissions:
assets.update(perm.node.get_all_assets())
return assets