Commit fffa0def authored by ibuler's avatar ibuler

[Update] 修改api和view

parent d0ede246
...@@ -27,13 +27,16 @@ class AssetCreateForm(forms.ModelForm): ...@@ -27,13 +27,16 @@ class AssetCreateForm(forms.ModelForm):
'class': 'select2', 'data-placeholder': _('Admin user') 'class': 'select2', 'data-placeholder': _('Admin user')
}), }),
'labels': forms.SelectMultiple(attrs={ 'labels': forms.SelectMultiple(attrs={
'class': 'select2', 'data-placeholder': _('Labels') 'class': 'select2', 'data-placeholder': _('Label')
}), }),
'port': forms.TextInput(), 'port': forms.TextInput(),
'domain': forms.Select(attrs={ 'domain': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Domain') 'class': 'select2', 'data-placeholder': _('Domain')
}), }),
} }
labels = {
'nodes': _("Node"),
}
help_texts = { help_texts = {
'hostname': '* required', 'hostname': '* required',
'ip': '* required', 'ip': '* required',
...@@ -57,19 +60,22 @@ class AssetUpdateForm(forms.ModelForm): ...@@ -57,19 +60,22 @@ class AssetUpdateForm(forms.ModelForm):
] ]
widgets = { widgets = {
'nodes': forms.SelectMultiple(attrs={ 'nodes': forms.SelectMultiple(attrs={
'class': 'select2', 'data-placeholder': _('Nodes') 'class': 'select2', 'data-placeholder': _('Node')
}), }),
'admin_user': forms.Select(attrs={ 'admin_user': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Admin user') 'class': 'select2', 'data-placeholder': _('Admin user')
}), }),
'labels': forms.SelectMultiple(attrs={ 'labels': forms.SelectMultiple(attrs={
'class': 'select2', 'data-placeholder': _('Labels') 'class': 'select2', 'data-placeholder': _('Label')
}), }),
'port': forms.TextInput(), 'port': forms.TextInput(),
'domain': forms.Select(attrs={ 'domain': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Domain') 'class': 'select2', 'data-placeholder': _('Domain')
}), }),
} }
labels = {
'nodes': _("Node"),
}
help_texts = { help_texts = {
'hostname': '* required', 'hostname': '* required',
'ip': '* required', 'ip': '* required',
...@@ -116,10 +122,10 @@ class AssetBulkUpdateForm(forms.ModelForm): ...@@ -116,10 +122,10 @@ class AssetBulkUpdateForm(forms.ModelForm):
] ]
widgets = { widgets = {
'labels': forms.SelectMultiple( 'labels': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select labels')} attrs={'class': 'select2', 'data-placeholder': _('Label')}
), ),
'nodes': forms.SelectMultiple( 'nodes': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select nodes')} attrs={'class': 'select2', 'data-placeholder': _('Node')}
), ),
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
import logging import logging
import uuid
from django.core.cache import cache from django.core.cache import cache
from django.db import models from django.db import models
...@@ -100,10 +101,11 @@ class SystemUser(AssetUser): ...@@ -100,10 +101,11 @@ class SystemUser(AssetUser):
) )
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes")) nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets"))
priority = models.IntegerField(default=10, verbose_name=_("Priority")) priority = models.IntegerField(default=10, verbose_name=_("Priority"))
protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol')) protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
sudo = models.TextField(default='/sbin/ifconfig', verbose_name=_('Sudo')) sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo'))
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
def __str__(self): def __str__(self):
...@@ -119,9 +121,8 @@ class SystemUser(AssetUser): ...@@ -119,9 +121,8 @@ class SystemUser(AssetUser):
'auto_push': self.auto_push, 'auto_push': self.auto_push,
} }
@property def get_assets(self):
def assets(self): assets = set(self.assets.all())
assets = set()
for node in self.nodes.all(): for node in self.nodes.all():
assets.update(set(node.get_all_assets())) assets.update(set(node.get_all_assets()))
return assets return assets
...@@ -168,6 +169,3 @@ class SystemUser(AssetUser): ...@@ -168,6 +169,3 @@ class SystemUser(AssetUser):
except IntegrityError: except IntegrityError:
print('Error continue') print('Error continue')
continue continue
...@@ -34,7 +34,7 @@ class SystemUserSerializer(serializers.ModelSerializer): ...@@ -34,7 +34,7 @@ class SystemUserSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_assets_amount(obj): def get_assets_amount(obj):
return len(obj.assets) return len(obj.get_assets())
class SystemUserAuthSerializer(AuthSerializer): class SystemUserAuthSerializer(AuthSerializer):
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from collections import defaultdict
from django.db.models.signals import post_save, m2m_changed from django.db.models.signals import post_save, m2m_changed
from django.dispatch import receiver from django.dispatch import receiver
from common.utils import get_logger from common.utils import get_logger
from .models import Asset, SystemUser, Node from .models import Asset, SystemUser, Node
from .tasks import update_assets_hardware_info_util, \ from .tasks import update_assets_hardware_info_util, \
test_asset_connectability_util, push_system_user_to_node, \ test_asset_connectability_util, push_system_user_to_assets
push_node_system_users_to_asset
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -31,7 +30,6 @@ def set_asset_root_node(asset): ...@@ -31,7 +30,6 @@ def set_asset_root_node(asset):
@receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier") @receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier")
def on_asset_created_or_update(sender, instance=None, created=False, **kwargs): def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
# set_asset_root_node(instance)
if created: if created:
logger.info("Asset `{}` create signal received".format(instance)) logger.info("Asset `{}` create signal received".format(instance))
update_asset_hardware_info_on_created(instance) update_asset_hardware_info_on_created(instance)
...@@ -41,25 +39,39 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs): ...@@ -41,25 +39,39 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
@receiver(post_save, sender=SystemUser, dispatch_uid="my_unique_identifier") @receiver(post_save, sender=SystemUser, dispatch_uid="my_unique_identifier")
def on_system_user_update(sender, instance=None, created=True, **kwargs): def on_system_user_update(sender, instance=None, created=True, **kwargs):
if instance and not created: if instance and not created:
for node in instance.nodes.all(): logger.info("System user `{}` update signal received".format(instance))
push_system_user_to_node(instance, node) assets = instance.assets.all()
push_system_user_to_assets.delay(instance, assets)
@receiver(m2m_changed, sender=SystemUser.nodes.through) @receiver(m2m_changed, sender=SystemUser.nodes.through)
def on_system_user_node_change(sender, instance=None, **kwargs): def on_system_user_nodes_change(sender, instance=None, **kwargs):
if instance and kwargs["action"] == "post_add":
assets = set()
nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
for node in nodes:
assets.update(set(node.get_all_assets()))
instance.assets.add(*tuple(assets))
@receiver(m2m_changed, sender=SystemUser.assets.through)
def on_system_user_assets_change(sender, instance=None, **kwargs):
if instance and kwargs["action"] == "post_add": if instance and kwargs["action"] == "post_add":
for pk in kwargs['pk_set']: assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
node = kwargs['model'].objects.get(pk=pk) push_system_user_to_assets(instance, assets)
push_system_user_to_node(instance, node)
@receiver(m2m_changed, sender=Asset.nodes.through) @receiver(m2m_changed, sender=Asset.nodes.through)
def on_asset_node_changed(sender, instance=None, **kwargs): def on_asset_node_changed(sender, instance=None, **kwargs):
if isinstance(instance, Asset) and kwargs['action'] == 'post_add': if isinstance(instance, Asset) and kwargs['action'] == 'post_add':
logger.debug("Asset node change signal received") logger.debug("Asset node change signal received")
for pk in kwargs['pk_set']: nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
node = kwargs['model'].objects.get(pk=pk) system_users_assets = defaultdict(set)
push_node_system_users_to_asset(node, [instance]) system_users = SystemUser.objects.filter(nodes__in=nodes)
for system_user in system_users:
system_users_assets[system_user].update({instance})
for system_user, assets in system_users_assets.items():
system_user.assets.add(*tuple(assets))
@receiver(m2m_changed, sender=Asset.nodes.through) @receiver(m2m_changed, sender=Asset.nodes.through)
...@@ -67,5 +79,6 @@ def on_node_assets_changed(sender, instance=None, **kwargs): ...@@ -67,5 +79,6 @@ def on_node_assets_changed(sender, instance=None, **kwargs):
if isinstance(instance, Node) and kwargs['action'] == 'post_add': if isinstance(instance, Node) and kwargs['action'] == 'post_add':
logger.debug("Node assets change signal received") logger.debug("Node assets change signal received")
assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
push_node_system_users_to_asset(instance, assets) system_users = SystemUser.objects.filter(nodes=instance)
for system_user in system_users:
system_user.assets.add(*tuple(assets))
...@@ -386,52 +386,17 @@ def push_system_user_util(system_users, assets, task_name): ...@@ -386,52 +386,17 @@ def push_system_user_util(system_users, assets, task_name):
return task.run() return task.run()
def get_node_push_system_user_task_name(system_user, node):
# return _("Push system user to node: {} => {}").format(
return _("推送系统用户到节点资产: {} => {}").format(
system_user.name,
node.value
)
@shared_task
def push_system_user_to_node(system_user, node):
logger.info("Start push system user node: {} => {}".format(system_user.name, node.value))
assets = node.get_all_assets()
task_name = get_node_push_system_user_task_name(system_user, node)
push_system_user_util([system_user], assets, task_name)
@shared_task
def push_system_user_related_nodes(system_user):
if not system_user.is_need_push():
msg = "push system user `{}` passed, may be not auto push or ssh " \
"protocol is not ssh".format(system_user.name)
logger.info(msg)
return
nodes = system_user.nodes.all()
for node in nodes:
push_system_user_to_node(system_user, node)
@shared_task @shared_task
def push_system_user_to_assets_manual(system_user): def push_system_user_to_assets_manual(system_user):
push_system_user_related_nodes(system_user) assets = system_user.get_assets()
task_name = "推送系统用户到入资产: {}".format(system_user.name)
return push_system_user_util([system_user], assets, task_name=task_name)
def push_node_system_users_to_asset(node, assets): @shared_task
system_users = [] def push_system_user_to_assets(system_user, assets):
nodes = node.ancestor_with_node task_name = _("推送系统用户到入资产: {}").format(system_user.name)
# 获取该节点所有父节点有的系统用户, 然后推送 return push_system_user_util.delay([system_user], assets, task_name)
for n in nodes:
system_users.extend(list(n.systemuser_set.all()))
if system_users:
# task_name = _("Push system users to node: {}").format(node.value)
task_name = _("推送节点系统用户到新加入资产中: {}").format(node.value)
push_system_user_util.delay(system_users, assets, task_name)
# @shared_task # @shared_task
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<div class="form-group {% if form.errors.labels %} has-error {% endif %}"> <div class="form-group {% if form.errors.labels %} has-error {% endif %}">
<label for="{{ form.labels.id_for_label }}" class="col-md-2 control-label">{% trans 'Label' %}</label> <label for="{{ form.labels.id_for_label }}" class="col-md-2 control-label">{% trans 'Label' %}</label>
<div class="col-md-9"> <div class="col-md-9">
<select name="labels" class="select2 labels" data-placeholder="{% trans 'Select labels' %}" style="width: 100%" multiple="" tabindex="4" id="{{ form.labels.id_for_label }}"> <select name="labels" class="select2 labels" data-placeholder="{% trans 'Label' %}" style="width: 100%" multiple="" tabindex="4" id="{{ form.labels.id_for_label }}">
{% for name, labels in form.labels.field.queryset|group_labels %} {% for name, labels in form.labels.field.queryset|group_labels %}
<optgroup label="{{ name }}"> <optgroup label="{{ name }}">
{% for label in labels %} {% for label in labels %}
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
<div class="form-group"> <div class="form-group">
<label for="{{ form.labels.id_for_label }}" class="col-md-2 control-label">{% trans 'Label' %}</label> <label for="{{ form.labels.id_for_label }}" class="col-md-2 control-label">{% trans 'Label' %}</label>
<div class="col-md-9"> <div class="col-md-9">
<select name="labels" class="select2 labels" data-placeholder="Select labels" style="width: 100%" multiple="" tabindex="4" id="{{ form.labels.id_for_label }}"> <select name="labels" class="select2 labels" data-placeholder="{% trans 'Label' %}" style="width: 100%" multiple="" tabindex="4" id="{{ form.labels.id_for_label }}">
{% for name, labels in form.labels.field.queryset|group_labels %} {% for name, labels in form.labels.field.queryset|group_labels %}
<optgroup label="{{ name }}"> <optgroup label="{{ name }}">
{% for label in labels %} {% for label in labels %}
......
...@@ -7,9 +7,9 @@ from rest_framework.generics import ListAPIView, get_object_or_404 ...@@ -7,9 +7,9 @@ from rest_framework.generics import ListAPIView, get_object_or_404
from rest_framework import viewsets from rest_framework import viewsets
from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser
from .utils import NodePermissionUtil from .utils import AssetPermissionUtil
from .models import NodePermission from .models import AssetPermission
from .hands import AssetGrantedSerializer, User, UserGroup, Asset, \ from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \
NodeGrantedSerializer, SystemUser, NodeSerializer NodeGrantedSerializer, SystemUser, NodeSerializer
from . import serializers from . import serializers
...@@ -18,7 +18,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): ...@@ -18,7 +18,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
""" """
资产授权列表的增删改查api 资产授权列表的增删改查api
""" """
queryset = NodePermission.objects.all() queryset = AssetPermission.objects.all()
serializer_class = serializers.AssetPermissionCreateUpdateSerializer serializer_class = serializers.AssetPermissionCreateUpdateSerializer
permission_classes = (IsSuperUser,) permission_classes = (IsSuperUser,)
...@@ -27,15 +27,6 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): ...@@ -27,15 +27,6 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
return serializers.AssetPermissionListSerializer return serializers.AssetPermissionListSerializer
return self.serializer_class return self.serializer_class
def get_queryset(self):
queryset = super().get_queryset()
node_id = self.request.query_params.get('node_id')
if node_id:
queryset = queryset.filter(node__id=node_id)
return queryset
class UserGrantedAssetsApi(ListAPIView): class UserGrantedAssetsApi(ListAPIView):
""" """
...@@ -53,7 +44,7 @@ class UserGrantedAssetsApi(ListAPIView): ...@@ -53,7 +44,7 @@ class UserGrantedAssetsApi(ListAPIView):
else: else:
user = self.request.user user = self.request.user
for k, v in NodePermissionUtil.get_user_assets(user).items(): for k, v in AssetPermissionUtil.get_user_assets(user).items():
if k.is_unixlike(): if k.is_unixlike():
system_users_granted = [s for s in v if s.protocol == 'ssh'] system_users_granted = [s for s in v if s.protocol == 'ssh']
else: else:
...@@ -78,14 +69,14 @@ class UserGrantedNodesApi(ListAPIView): ...@@ -78,14 +69,14 @@ class UserGrantedNodesApi(ListAPIView):
user = get_object_or_404(User, id=user_id) user = get_object_or_404(User, id=user_id)
else: else:
user = self.request.user user = self.request.user
nodes = NodePermissionUtil.get_user_nodes(user) nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
return nodes.keys() return nodes.keys()
class UserGrantedNodesWithAssetsApi(ListAPIView): class UserGrantedNodesWithAssetsApi(ListAPIView):
""" """
授权用户的资产组,注:这里的资产组并非是授权列表中授权的, 授权用户的资产组,注:这里的资产组并非是授权列表中授权的,
而是把所有资产取出来,然后反查出所有资产组,然后合并得到, 而是把所有资产取出来,然后反查出所有节点,然后合并得到,
结果里也包含资产组下授权的资产 结果里也包含资产组下授权的资产
数据结构如下: 数据结构如下:
[ [
...@@ -121,18 +112,12 @@ class UserGrantedNodesWithAssetsApi(ListAPIView): ...@@ -121,18 +112,12 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
else: else:
user = get_object_or_404(User, id=user_id) user = get_object_or_404(User, id=user_id)
nodes = NodePermissionUtil.get_user_nodes_with_assets(user) nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
assets = {} for node, _assets in nodes.items():
for k, v in NodePermissionUtil.get_user_assets(user).items(): assets = _assets.keys()
if k.is_unixlike(): for asset, system_users in _assets.items():
system_users_granted = [s for s in v if s.protocol == 'ssh'] asset.system_users_granted = system_users
else: node.assets_granted = assets
system_users_granted = [s for s in v if s.protocol == 'rdp']
assets[k] = system_users_granted
for node, v in nodes.items():
for asset in v['assets']:
asset.system_users_granted = assets[asset]
node.assets_granted = v['assets']
queryset.append(node) queryset.append(node)
return queryset return queryset
...@@ -142,6 +127,26 @@ class UserGrantedNodesWithAssetsApi(ListAPIView): ...@@ -142,6 +127,26 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
return super().get_permissions() return super().get_permissions()
class UserGrantedNodeAssetsApi(ListAPIView):
permission_classes = (IsSuperUserOrAppUser,)
serializer_class = AssetGrantedSerializer
def get_queryset(self):
user_id = self.kwargs.get('pk', '')
node_id = self.kwargs.get('node_id')
if user_id:
user = get_object_or_404(User, id=user_id)
else:
user = self.request.user
node = get_object_or_404(Node, id=node_id)
nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
assets = nodes.get(node, [])
for asset, system_users in assets.items():
asset.system_users_granted = system_users
return assets
class UserGroupGrantedAssetsApi(ListAPIView): class UserGroupGrantedAssetsApi(ListAPIView):
permission_classes = (IsSuperUser,) permission_classes = (IsSuperUser,)
serializer_class = AssetGrantedSerializer serializer_class = AssetGrantedSerializer
...@@ -154,7 +159,7 @@ class UserGroupGrantedAssetsApi(ListAPIView): ...@@ -154,7 +159,7 @@ class UserGroupGrantedAssetsApi(ListAPIView):
return queryset return queryset
user_group = get_object_or_404(UserGroup, id=user_group_id) user_group = get_object_or_404(UserGroup, id=user_group_id)
assets = NodePermissionUtil.get_user_group_assets(user_group) assets = AssetPermissionUtil.get_user_group_assets(user_group)
for k, v in assets.items(): for k, v in assets.items():
k.system_users_granted = v k.system_users_granted = v
queryset.append(k) queryset.append(k)
...@@ -171,8 +176,8 @@ class UserGroupGrantedNodesApi(ListAPIView): ...@@ -171,8 +176,8 @@ class UserGroupGrantedNodesApi(ListAPIView):
if group_id: if group_id:
group = get_object_or_404(UserGroup, id=group_id) group = get_object_or_404(UserGroup, id=group_id)
nodes = NodePermissionUtil.get_user_group_nodes(group) nodes = AssetPermissionUtil.get_user_group_nodes_with_assets(group)
queryset = nodes.keys() return nodes.keys()
return queryset return queryset
...@@ -188,15 +193,33 @@ class UserGroupGrantedNodesWithAssetsApi(ListAPIView): ...@@ -188,15 +193,33 @@ class UserGroupGrantedNodesWithAssetsApi(ListAPIView):
return queryset return queryset
user_group = get_object_or_404(UserGroup, id=user_group_id) user_group = get_object_or_404(UserGroup, id=user_group_id)
nodes = NodePermissionUtil.get_user_group_nodes_with_assets(user_group) nodes = AssetPermissionUtil.get_user_group_nodes_with_assets(user_group)
for node, v in nodes.items(): for node, _assets in nodes.items():
for asset in v['assets']: assets = _assets.keys()
asset.system_users_granted = v['system_users'] for asset, system_users in _assets.items():
node.assets_granted = v['assets'] asset.system_users_granted = system_users
node.assets_granted = assets
queryset.append(node) queryset.append(node)
return queryset return queryset
class UserGroupGrantedNodeAssetsApi(ListAPIView):
permission_classes = (IsSuperUserOrAppUser,)
serializer_class = AssetGrantedSerializer
def get_queryset(self):
user_group_id = self.kwargs.get('pk', '')
node_id = self.kwargs.get('node_id')
user_group = get_object_or_404(UserGroup, id=user_group_id)
node = get_object_or_404(Node, id=node_id)
nodes = AssetPermissionUtil.get_user_group_nodes_with_assets(user_group)
assets = nodes.get(node, [])
for asset, system_users in assets.items():
asset.system_users_granted = system_users
return assets
class ValidateUserAssetPermissionView(APIView): class ValidateUserAssetPermissionView(APIView):
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
...@@ -210,7 +233,7 @@ class ValidateUserAssetPermissionView(APIView): ...@@ -210,7 +233,7 @@ class ValidateUserAssetPermissionView(APIView):
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)
assets_granted = NodePermissionUtil.get_user_assets(user) assets_granted = AssetPermissionUtil.get_user_assets(user)
if system_user in assets_granted.get(asset, []): if system_user in assets_granted.get(asset, []):
return Response({'msg': True}, status=200) return Response({'msg': True}, status=200)
else: else:
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from common.utils import get_object_or_none from .models import AssetPermission
from common.fields import StringIDField
from .models import AssetPermission, NodePermission
class AssetPermissionCreateUpdateSerializer(serializers.ModelSerializer): class AssetPermissionCreateUpdateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = NodePermission model = AssetPermission
fields = [ exclude = ('id', 'create_by', 'date_created')
'id', 'node', 'user_group', 'system_user',
'is_active', 'date_expired'
]
class AssetPermissionListSerializer(serializers.ModelSerializer): class AssetPermissionListSerializer(serializers.ModelSerializer):
node = StringIDField(read_only=True)
user_group = StringIDField(read_only=True)
system_user = StringIDField(read_only=True)
class Meta: class Meta:
model = NodePermission model = AssetPermission
fields = '__all__' fields = '__all__'
...@@ -40,14 +30,3 @@ class AssetPermissionUpdateAssetSerializer(serializers.ModelSerializer): ...@@ -40,14 +30,3 @@ class AssetPermissionUpdateAssetSerializer(serializers.ModelSerializer):
model = AssetPermission model = AssetPermission
fields = ['id', 'assets'] fields = ['id', 'assets']
class UserAssetPermissionCreateUpdateSerializer(AssetPermissionCreateUpdateSerializer):
is_inherited = serializers.SerializerMethodField()
@staticmethod
def get_is_inherited(obj):
if getattr(obj, 'inherited', ''):
return True
else:
return False
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.db.models.signals import m2m_changed
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver from django.dispatch import receiver
from common.utils import get_logger from common.utils import get_logger
from .models import NodePermission from .models import AssetPermission
logger = get_logger(__file__) logger = get_logger(__file__)
@receiver(post_save, sender=NodePermission, dispatch_uid="my_unique_identifier") @receiver(m2m_changed, sender=AssetPermission.nodes.through)
def on_asset_permission_create_or_update(sender, instance=None, **kwargs): def on_permission_nodes_changed(sender, instance=None, **kwargs):
if instance and instance.node and instance.system_user: if isinstance(instance, AssetPermission) and kwargs['action'] == 'post_add':
instance.system_user.nodes.add(instance.node) logger.debug("Asset permission nodes change signal received")
nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
system_users = instance.system_users.all()
for system_user in system_users:
system_user.nodes.add(*tuple(nodes))
@receiver(m2m_changed, sender=AssetPermission.assets.through)
def on_permission_assets_changed(sender, instance=None, **kwargs):
if isinstance(instance, AssetPermission) and kwargs['action'] == 'post_add':
logger.debug("Asset permission assets change signal received")
assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
system_users = instance.system_users.all()
for system_user in system_users:
system_user.assets.add(*tuple(assets))
@receiver(m2m_changed, sender=AssetPermission.system_users.through)
def on_permission_system_users_changed(sender, instance=None, **kwargs):
if isinstance(instance, AssetPermission) and kwargs['action'] == 'post_add':
logger.debug("Asset permission system_users change signal received")
system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
assets = instance.assets.all()
nodes = instance.nodes.all()
for system_user in system_users:
system_user.nodes.add(*tuple(nodes))
system_user.assets.add(*tuple(assets))
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="{% url 'perms:asset-permission-update' pk=object.id %}" class="btn btn-xs btn-info">{% trans "Update" %}</a> <a href="{% url 'perms:asset-permission-update' pk=object.id %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>
<a href="" class="btn btn-xs btn-danger m-l-xs">{% trans "Delete" %}</a> <a data-uid="{{ object.id }}" class="btn btn-xs btn-danger m-l-xs btn-delete">{% trans "Delete" %}</a>
</td> </td>
<td>{{ object.users_detail }}</td> <td>{{ object.users_detail }}</td>
<td>{{ object.user_groups_detail }}</td> <td>{{ object.user_groups_detail }}</td>
...@@ -147,6 +147,15 @@ ...@@ -147,6 +147,15 @@
calendarWeeks: true, calendarWeeks: true,
autoclose: true autoclose: true
}); });
}).on('click', '.btn-delete', function () {
var $this = $(this);
var uid = $this.data('uid');
var the_url = '{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
objectDelete($this, name, the_url);
setTimeout( function () {
window.reload();
}, 1000);
}); });
</script> </script>
{% endblock %} {% endblock %}
......
...@@ -15,6 +15,8 @@ urlpatterns = [ ...@@ -15,6 +15,8 @@ urlpatterns = [
url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(), name='my-assets'), url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(), name='my-assets'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGrantedNodesApi.as_view(), name='user-nodes'), url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGrantedNodesApi.as_view(), name='user-nodes'),
url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(), name='my-nodes'), url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(), name='my-nodes'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'),
url(r'^v1/user/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'), url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'),
url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='my-nodes-assets'), url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='my-nodes-assets'),
...@@ -22,6 +24,7 @@ urlpatterns = [ ...@@ -22,6 +24,7 @@ urlpatterns = [
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'), url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'), url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'),
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGroupGrantedNodesWithAssetsApi.as_view(), name='user-group-nodes-assets'), url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGroupGrantedNodesWithAssetsApi.as_view(), name='user-group-nodes-assets'),
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedNodeAssetsApi.as_view(), name='user-group-node-assets'),
# 验证用户是否有某个资产和系统用户的权限 # 验证用户是否有某个资产和系统用户的权限
url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'), url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'),
......
...@@ -12,7 +12,7 @@ from .models import AssetPermission ...@@ -12,7 +12,7 @@ from .models import AssetPermission
logger = get_logger(__file__) logger = get_logger(__file__)
class AssetPermissionUtils: class AssetPermissionUtil:
@staticmethod @staticmethod
def get_user_permissions(user): def get_user_permissions(user):
...@@ -81,6 +81,23 @@ class AssetPermissionUtils: ...@@ -81,6 +81,23 @@ class AssetPermissionUtils:
assets[asset].update(set(_system_users)) assets[asset].update(set(_system_users))
return assets return assets
@classmethod
def get_user_group_nodes_with_assets(cls, user):
"""
:param user:
:return: {node: {asset: set(su1, su2)}}
"""
nodes = defaultdict(dict)
_assets = cls.get_user_group_assets(user)
for asset, _system_users in _assets.items():
_nodes = asset.get_nodes()
for node in _nodes:
if asset in nodes[node]:
nodes[node][asset].update(_system_users)
else:
nodes[node][asset] = _system_users
return nodes
@classmethod @classmethod
def get_user_assets_direct(cls, user): def get_user_assets_direct(cls, user):
assets = defaultdict(set) assets = defaultdict(set)
...@@ -142,7 +159,7 @@ class AssetPermissionUtils: ...@@ -142,7 +159,7 @@ class AssetPermissionUtils:
return assets return assets
@classmethod @classmethod
def get_user_node_with_assets(cls, user): def get_user_nodes_with_assets(cls, user):
""" """
:param user: :param user:
:return: {node: {asset: set(su1, su2)}} :return: {node: {asset: set(su1, su2)}}
...@@ -178,8 +195,11 @@ class AssetPermissionUtils: ...@@ -178,8 +195,11 @@ class AssetPermissionUtils:
return system_users return system_users
# Abandon
class NodePermissionUtil: class NodePermissionUtil:
"""
"""
@staticmethod @staticmethod
def get_user_group_permissions(user_group): def get_user_group_permissions(user_group):
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<th class="text-center">{% trans 'Hostname' %}</th> <th class="text-center">{% trans 'Hostname' %}</th>
<th class="text-center">{% trans 'IP' %}</th> <th class="text-center">{% trans 'IP' %}</th>
<th class="text-center">{% trans 'Active' %}</th> <th class="text-center">{% trans 'Active' %}</th>
<th class="text-center">{% trans 'Reachable' %}</th> <th class="text-center">{% trans 'System users' %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -63,6 +63,8 @@ ...@@ -63,6 +63,8 @@
<script> <script>
var zTree; var zTree;
var inited = false; var inited = false;
var url;
var asset_table;
function initTable() { function initTable() {
if (inited){ if (inited){
...@@ -86,31 +88,28 @@ function initTable() { ...@@ -86,31 +88,28 @@ function initTable() {
} }
}}, }},
{targets: 4, createdCell: function (td, cellData) { {targets: 4, createdCell: function (td, cellData) {
if (cellData === 'Unknown'){ var users = [];
$(td).html('<i class="fa fa-circle text-warning"></i>') $.each(cellData, function (id, data) {
} else if (!cellData) { users.push(data.name);
$(td).html('<i class="fa fa-circle text-danger"></i>') });
} else { $(td).html(users.join(', '))
$(td).html('<i class="fa fa-circle text-navy"></i>')
}
}} }}
], ],
ajax_url: '{% url "api-assets:asset-list" %}', ajax_url: url,
columns: [ columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "id"}, {data: "hostname" }, {data: "ip" },
{data: "is_active", orderable: false }, {data: "is_active", orderable: false },
{data: "is_connective", orderable: false} {data: "system_users_granted", orderable: false}
] ]
}; };
asset_table = jumpserver.initServerSideDataTable(options); return jumpserver.initDataTable(options);
return asset_table
} }
function onSelected(event, treeNode) { function onSelected(event, treeNode) {
initTable(); url = '{% url "api-perms:user-node-assets" pk=object.id node_id=DEFAULT_PK %}';
var url = asset_table.ajax.url(); url = url.replace("{{ DEFAULT_PK }}", treeNode.id);
url = setUrlParam(url, "node_id", treeNode.id);
setCookie('node_selected', treeNode.id); setCookie('node_selected', treeNode.id);
asset_table = initTable();
asset_table.ajax.url(url); asset_table.ajax.url(url);
asset_table.ajax.reload(); asset_table.ajax.reload();
} }
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
<script> <script>
var zTree; var zTree;
var inited = false; var inited = false;
var url;
function initTable() { function initTable() {
if (inited){ if (inited){
...@@ -86,31 +87,29 @@ function initTable() { ...@@ -86,31 +87,29 @@ function initTable() {
} }
}}, }},
{targets: 4, createdCell: function (td, cellData) { {targets: 4, createdCell: function (td, cellData) {
if (cellData === 'Unknown'){ var users = [];
$(td).html('<i class="fa fa-circle text-warning"></i>') $.each(cellData, function (id, data) {
} else if (!cellData) { users.push(data.name);
$(td).html('<i class="fa fa-circle text-danger"></i>') });
} else { $(td).html(users.join(', '))
$(td).html('<i class="fa fa-circle text-navy"></i>')
}
}} }}
], ],
ajax_url: '{% url "api-assets:asset-list" %}', ajax_url: url,
columns: [ columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "id"}, {data: "hostname" }, {data: "ip" },
{data: "is_active", orderable: false }, {data: "is_active", orderable: false },
{data: "is_connective", orderable: false} {data: "system_users_granted", orderable: false}
] ]
}; };
asset_table = jumpserver.initServerSideDataTable(options); asset_table = jumpserver.initDataTable(options);
return asset_table return asset_table
} }
function onSelected(event, treeNode) { function onSelected(event, treeNode) {
initTable(); url = '{% url "api-perms:user-group-node-assets" pk=object.id node_id=DEFAULT_PK %}';
var url = asset_table.ajax.url(); url = url.replace("{{ DEFAULT_PK }}", treeNode.id);
url = setUrlParam(url, "node_id", treeNode.id);
setCookie('node_selected', treeNode.id); setCookie('node_selected', treeNode.id);
asset_table = initTable();
asset_table.ajax.url(url); asset_table.ajax.url(url);
asset_table.ajax.reload(); asset_table.ajax.reload();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment