Commit b7021b5e authored by ibuler's avatar ibuler

[Update] 支持收集资产上的用户

parent 5464c884
...@@ -36,6 +36,7 @@ class AssetViewSet(OrgBulkModelViewSet): ...@@ -36,6 +36,7 @@ class AssetViewSet(OrgBulkModelViewSet):
serializer_class = serializers.AssetSerializer serializer_class = serializers.AssetSerializer
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend] extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend]
custom_filter_fields = ['admin_user_id']
def set_assets_node(self, assets): def set_assets_node(self, assets):
if not isinstance(assets, list): if not isinstance(assets, list):
......
...@@ -6,6 +6,7 @@ from assets.models import GatheredUser ...@@ -6,6 +6,7 @@ from assets.models import GatheredUser
from common.permissions import IsOrgAdmin from common.permissions import IsOrgAdmin
from ..serializers import GatheredUserSerializer from ..serializers import GatheredUserSerializer
from ..filters import AssetRelatedByNodeFilterBackend
__all__ = ['GatheredUserViewSet'] __all__ = ['GatheredUserViewSet']
...@@ -15,6 +16,7 @@ class GatheredUserViewSet(OrgModelViewSet): ...@@ -15,6 +16,7 @@ class GatheredUserViewSet(OrgModelViewSet):
queryset = GatheredUser.objects.all() queryset = GatheredUser.objects.all()
serializer_class = GatheredUserSerializer serializer_class = GatheredUserSerializer
permission_classes = [IsOrgAdmin] permission_classes = [IsOrgAdmin]
extra_filter_backends = [AssetRelatedByNodeFilterBackend]
filter_fields = ['asset', 'username', 'present'] filter_fields = ['asset', 'username', 'present']
search_fields = ['username', 'asset__ip', 'asset__hostname'] search_fields = ['username', 'asset__ip', 'asset__hostname']
......
...@@ -12,63 +12,54 @@ from .models import Node, Label ...@@ -12,63 +12,54 @@ from .models import Node, Label
class AssetByNodeFilterBackend(filters.BaseFilterBackend): class AssetByNodeFilterBackend(filters.BaseFilterBackend):
fields = ['node', 'all'] fields = ['node', 'all']
# def filter_node(self, queryset):
# node_id = self.request.query_params.get("node_id")
# if not node_id:
# return queryset
#
# node = get_object_or_404(Node, id=node_id)
# show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true')
#
# # 当前节点是顶层节点, 并且仅显示直接资产
# if node.is_org_root() and show_current_asset:
# queryset = queryset.filter(
# Q(nodes=node_id) | Q(nodes__isnull=True)
# ).distinct()
# # 当前节点是顶层节点,显示所有资产
# elif node.is_org_root() and not show_current_asset:
# return queryset
# # 当前节点不是鼎城节点,只显示直接资产
# elif not node.is_org_root() and show_current_asset:
# queryset = queryset.filter(nodes=node)
# else:
# children = node.get_all_children(with_self=True)
# queryset = queryset.filter(nodes__in=children).distinct()
# return queryset
def get_schema_fields(self, view): def get_schema_fields(self, view):
return [ return [
coreapi.Field( coreapi.Field(
name=field, location='query', required=False, name=field, location='query', required=False,
type='string', example='', description='' type='string', example='', description='', schema=None,
) )
for field in self.fields for field in self.fields
] ]
def filter_queryset(self, request, queryset, view): @staticmethod
node_id = dict_get_any(request.query_params, ['node', 'node_id']) def is_query_all(request):
if not node_id:
return queryset
query_all_arg = request.query_params.get('all') query_all_arg = request.query_params.get('all')
show_current_asset_arg = request.query_params.get('show_current_asset') show_current_asset_arg = request.query_params.get('show_current_asset')
query_all = query_all_arg == '1' query_all = query_all_arg == '1'
if show_current_asset_arg is not None: if show_current_asset_arg is not None:
query_all = show_current_asset_arg != '1' query_all = show_current_asset_arg != '1'
return query_all
@staticmethod
def get_query_node(request):
node_id = dict_get_any(request.query_params, ['node', 'node_id'])
if not node_id:
return None, False
if is_uuid(node_id): if is_uuid(node_id):
node = get_object_or_none(Node, id=node_id) node = get_object_or_none(Node, id=node_id)
else: else:
node = get_object_or_none(Node, key=node_id) node = get_object_or_none(Node, key=node_id)
return node, True
if not node: @staticmethod
return queryset.none() def perform_query(pattern, queryset):
return queryset.filter(nodes__key__regex=pattern)
def filter_queryset(self, request, queryset, view):
node, has_query_arg = self.get_query_node(request)
if not has_query_arg:
return queryset
if node is None:
return queryset.none()
query_all = self.is_query_all(request)
if query_all: if query_all:
pattern = node.get_all_children_pattern(with_self=True) pattern = node.get_all_children_pattern(with_self=True)
else: else:
pattern = node.get_children_key_pattern(with_self=True) pattern = node.get_children_key_pattern(with_self=True)
return queryset.filter(nodes__key__regex=pattern) return self.perform_query(pattern, queryset)
class LabelFilterBackend(filters.BaseFilterBackend): class LabelFilterBackend(filters.BaseFilterBackend):
...@@ -117,3 +108,8 @@ class LabelFilterBackend(filters.BaseFilterBackend): ...@@ -117,3 +108,8 @@ class LabelFilterBackend(filters.BaseFilterBackend):
return queryset return queryset
class AssetRelatedByNodeFilterBackend(AssetByNodeFilterBackend):
@staticmethod
def perform_query(pattern, queryset):
return queryset.filter(asset__nodes__key__regex=pattern).distinct()
...@@ -18,10 +18,10 @@ class Migration(migrations.Migration): ...@@ -18,10 +18,10 @@ class Migration(migrations.Migration):
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')),
('present', models.BooleanField(default=True)), ('present', models.BooleanField(default=True, verbose_name='Present')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset')), ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')),
], ],
options={'ordering': ['asset'], 'verbose_name': 'GatherUser'}, options={'ordering': ['asset'], 'verbose_name': 'GatherUser'},
), ),
......
...@@ -11,10 +11,10 @@ __all__ = ['GatheredUser'] ...@@ -11,10 +11,10 @@ __all__ = ['GatheredUser']
class GatheredUser(OrgModelMixin): class GatheredUser(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE) asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_("Asset"))
username = models.CharField(max_length=32, blank=True, db_index=True, username = models.CharField(max_length=32, blank=True, db_index=True,
verbose_name=_('Username')) verbose_name=_('Username'))
present = models.BooleanField(default=True) present = models.BooleanField(default=True, verbose_name=_("Present"))
date_created = models.DateTimeField(auto_now_add=True, date_created = models.DateTimeField(auto_now_add=True,
verbose_name=_("Date created")) verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True, date_updated = models.DateTimeField(auto_now=True,
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from ..models import GatheredUser from django.utils.translation import ugettext_lazy as _
from orgs.mixins.serializers import OrgResourceModelSerializerMixin from orgs.mixins.serializers import OrgResourceModelSerializerMixin
from ..models import GatheredUser
class GatheredUserSerializer(OrgResourceModelSerializerMixin): class GatheredUserSerializer(OrgResourceModelSerializerMixin):
...@@ -14,3 +15,7 @@ class GatheredUserSerializer(OrgResourceModelSerializerMixin): ...@@ -14,3 +15,7 @@ class GatheredUserSerializer(OrgResourceModelSerializerMixin):
'present', 'date_created', 'date_updated' 'present', 'date_created', 'date_updated'
] ]
read_only_fields = fields read_only_fields = fields
labels = {
'hostname': _("Hostname"),
'ip': "IP"
}
...@@ -116,8 +116,9 @@ def gather_asset_users(assets, task_name=None): ...@@ -116,8 +116,9 @@ def gather_asset_users(assets, task_name=None):
for k, value in hosts_category.items(): for k, value in hosts_category.items():
if not value['hosts']: if not value['hosts']:
continue continue
_task_name = '{}: {}'.format(task_name, k)
task, created = update_or_create_ansible_task( task, created = update_or_create_ansible_task(
task_name=task_name, hosts=value['hosts'], tasks=value['tasks'], task_name=_task_name, hosts=value['hosts'], tasks=value['tasks'],
pattern='all', options=const.TASK_OPTIONS, pattern='all', options=const.TASK_OPTIONS,
run_as_admin=True, created_by=value['hosts'][0].org_id, run_as_admin=True, created_by=value['hosts'][0].org_id,
) )
......
...@@ -70,7 +70,6 @@ class IDSpmFilter(filters.BaseFilterBackend): ...@@ -70,7 +70,6 @@ class IDSpmFilter(filters.BaseFilterBackend):
class CustomFilter(filters.BaseFilterBackend): class CustomFilter(filters.BaseFilterBackend):
custom_filter_fields = [] # ["node", "asset"]
def get_schema_fields(self, view): def get_schema_fields(self, view):
fields = [] fields = []
...@@ -79,7 +78,10 @@ class CustomFilter(filters.BaseFilterBackend): ...@@ -79,7 +78,10 @@ class CustomFilter(filters.BaseFilterBackend):
type='string', example='', type='string', example='',
description='' description=''
) )
for field in self.custom_filter_fields: if not hasattr(view, 'custom_filter_fields'):
return []
for field in view.custom_filter_fields:
if isinstance(field, str): if isinstance(field, str):
defaults['name'] = field defaults['name'] = field
elif isinstance(field, dict): elif isinstance(field, dict):
......
This diff is collapsed.
...@@ -218,28 +218,32 @@ class AdHoc(models.Model): ...@@ -218,28 +218,32 @@ class AdHoc(models.Model):
hid = str(uuid.uuid4()) hid = str(uuid.uuid4())
history = AdHocRunHistory(id=hid, adhoc=self, task=self.task) history = AdHocRunHistory(id=hid, adhoc=self, task=self.task)
time_start = time.time() time_start = time.time()
date_start = timezone.now()
is_success = False
try: try:
date_start = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
history.date_start = timezone.now() print(_("{} Start task: {}").format(date_start_s, self.task.name))
print(_("{} Start task: {}").format(date_start, self.task.name))
raw, summary = self._run_only() raw, summary = self._run_only()
date_end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') is_success = summary.get('success', False)
print(_("{} Task finish").format(date_end))
history.is_finished = True
if summary.get('dark'):
history.is_success = False
else:
history.is_success = True
history.result = raw
history.summary = summary
return raw, summary return raw, summary
except Exception as e: except Exception as e:
logger.error(e, exc_info=True) logger.error(e, exc_info=True)
return {}, {"dark": {"all": str(e)}, "contacted": []} summary = {}
raw = {"dark": {"all": str(e)}, "contacted": []}
return raw, summary
finally: finally:
history.date_finished = timezone.now() date_end = timezone.now()
history.timedelta = time.time() - time_start date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
history.save() print(_("{} Task finish").format(date_end_s))
print('.\n\n.')
AdHocRunHistory.objects.filter(id=history.id).update(
date_start=date_start,
is_finished=True,
is_success=is_success,
date_finished=timezone.now(),
timedelta=time.time() - time_start
)
def _run_only(self): def _run_only(self):
runner = AdHocRunner(self.inventory, options=self.options) runner = AdHocRunner(self.inventory, options=self.options)
......
...@@ -20,12 +20,7 @@ class RootOrgViewMixin: ...@@ -20,12 +20,7 @@ class RootOrgViewMixin:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class OrgModelViewSet(CommonApiMixin, ModelViewSet): class OrgQuerySetMixin:
def get_queryset(self):
return super().get_queryset().all()
class OrgBulkModelViewSet(CommonApiMixin, BulkModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset().all() queryset = super().get_queryset().all()
if hasattr(self, 'swagger_fake_view'): if hasattr(self, 'swagger_fake_view'):
...@@ -36,6 +31,12 @@ class OrgBulkModelViewSet(CommonApiMixin, BulkModelViewSet): ...@@ -36,6 +31,12 @@ class OrgBulkModelViewSet(CommonApiMixin, BulkModelViewSet):
queryset = self.serializer_class.setup_eager_loading(queryset) queryset = self.serializer_class.setup_eager_loading(queryset)
return queryset return queryset
class OrgModelViewSet(CommonApiMixin, OrgQuerySetMixin, ModelViewSet):
pass
class OrgBulkModelViewSet(CommonApiMixin, OrgQuerySetMixin, BulkModelViewSet):
def allow_bulk_destroy(self, qs, filtered): def allow_bulk_destroy(self, qs, filtered):
if qs.count() <= filtered.count(): if qs.count() <= filtered.count():
return False return False
......
...@@ -7,7 +7,7 @@ from common.tree import TreeNodeSerializer ...@@ -7,7 +7,7 @@ from common.tree import TreeNodeSerializer
class UserAssetPermissionMixin(UserPermissionMixin): class UserAssetPermissionMixin(UserPermissionMixin):
util = AssetPermissionUtilV2(None) util = None
tree = None tree = None
def initial(self, *args, **kwargs): def initial(self, *args, **kwargs):
......
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