mirror of https://github.com/jumpserver/jumpserver
perf: Change secret record table dashboard
parent
49a811963c
commit
81daf33b16
|
@ -1,11 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.db.models import Max, Q, Subquery, OuterRef
|
||||
from rest_framework import status, mixins
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
from accounts import serializers
|
||||
from accounts.const import AutomationTypes
|
||||
from accounts.const import AutomationTypes, ChangeSecretRecordStatusChoice
|
||||
from accounts.filters import ChangeSecretRecordFilterSet
|
||||
from accounts.models import ChangeSecretAutomation, ChangeSecretRecord
|
||||
from accounts.tasks import execute_automation_record_task
|
||||
|
@ -34,7 +35,8 @@ class ChangeSecretAutomationViewSet(OrgBulkModelViewSet):
|
|||
|
||||
class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
||||
filterset_class = ChangeSecretRecordFilterSet
|
||||
search_fields = ('asset__address',)
|
||||
search_fields = ('asset__address', 'account_username')
|
||||
ordering_fields = ('date_finished',)
|
||||
tp = AutomationTypes.change_secret
|
||||
serializer_classes = {
|
||||
'default': serializers.ChangeSecretRecordSerializer,
|
||||
|
@ -43,6 +45,8 @@ class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
|||
rbac_perms = {
|
||||
'execute': 'accounts.add_changesecretexecution',
|
||||
'secret': 'accounts.view_changesecretrecord',
|
||||
'dashboard': 'accounts.view_changesecretrecord',
|
||||
'ignore_fail': 'accounts.view_changesecretrecord',
|
||||
}
|
||||
|
||||
def get_permissions(self):
|
||||
|
@ -53,9 +57,35 @@ class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
|||
]
|
||||
return super().get_permissions()
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = super().filter_queryset(queryset)
|
||||
|
||||
if self.action == 'dashboard':
|
||||
return self.get_dashboard_queryset(queryset)
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def get_dashboard_queryset(queryset):
|
||||
recent_dates = queryset.values('account').annotate(
|
||||
max_date_finished=Max('date_finished')
|
||||
)
|
||||
|
||||
recent_success_accounts = queryset.filter(
|
||||
account=OuterRef('account'),
|
||||
date_finished=Subquery(
|
||||
recent_dates.filter(account=OuterRef('account')).values('max_date_finished')[:1]
|
||||
)
|
||||
).filter(Q(status=ChangeSecretRecordStatusChoice.success) | Q(ignore_fail=True))
|
||||
|
||||
failed_records = queryset.filter(
|
||||
~Q(account__in=Subquery(recent_success_accounts.values('account'))),
|
||||
status=ChangeSecretRecordStatusChoice.failed
|
||||
)
|
||||
return failed_records
|
||||
|
||||
def get_queryset(self):
|
||||
qs = ChangeSecretRecord.get_valid_records()
|
||||
return qs.objects.filter(
|
||||
return qs.filter(
|
||||
execution__automation__type=self.tp
|
||||
)
|
||||
|
||||
|
@ -78,6 +108,17 @@ class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
|||
serializer = self.get_serializer(instance)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(methods=['get'], detail=False, url_path='dashboard')
|
||||
def dashboard(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['patch'], detail=True, url_path='ignore-fail')
|
||||
def ignore_fail(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
instance.ignore_fail = True
|
||||
instance.save(update_fields=['ignore_fail'])
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class ChangSecretExecutionViewSet(AutomationExecutionViewSet):
|
||||
rbac_perms = (
|
||||
|
|
|
@ -6,6 +6,7 @@ from django_filters import rest_framework as drf_filters
|
|||
|
||||
from assets.models import Node
|
||||
from common.drf.filters import BaseFilterSet
|
||||
from common.utils.timezone import local_zero_hour, local_now
|
||||
from .models import Account, GatheredAccount, ChangeSecretRecord
|
||||
|
||||
|
||||
|
@ -28,7 +29,7 @@ class AccountFilterSet(BaseFilterSet):
|
|||
latest_updated = drf_filters.BooleanFilter(method='filter_latest')
|
||||
latest_secret_changed = drf_filters.BooleanFilter(method='filter_latest')
|
||||
latest_secret_change_failed = drf_filters.BooleanFilter(method='filter_latest')
|
||||
risk = drf_filters.CharFilter(method='filter_risk',)
|
||||
risk = drf_filters.CharFilter(method='filter_risk', )
|
||||
long_time_no_change_secret = drf_filters.BooleanFilter(method='filter_long_time')
|
||||
long_time_no_verified = drf_filters.BooleanFilter(method='filter_long_time')
|
||||
|
||||
|
@ -127,6 +128,17 @@ class ChangeSecretRecordFilterSet(BaseFilterSet):
|
|||
account_username = drf_filters.CharFilter(field_name='account__username', lookup_expr='icontains')
|
||||
execution_id = drf_filters.CharFilter(field_name='execution_id', lookup_expr='exact')
|
||||
|
||||
days = drf_filters.NumberFilter(method='filter_days')
|
||||
|
||||
@staticmethod
|
||||
def filter_days(queryset, name, value):
|
||||
value = int(value)
|
||||
|
||||
dt = local_zero_hour()
|
||||
if value != 1:
|
||||
dt = local_now() - timezone.timedelta(days=value)
|
||||
return queryset.filter(date_finished__gte=dt)
|
||||
|
||||
class Meta:
|
||||
model = ChangeSecretRecord
|
||||
fields = ['id', 'status', 'asset_id', 'execution']
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.1.13 on 2024-12-02 03:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0017_serviceintegration'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='changesecretrecord',
|
||||
name='ignore_fail',
|
||||
field=models.BooleanField(default=False, verbose_name='Ignore fail'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='changesecretrecord',
|
||||
name='date_finished',
|
||||
field=models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Date finished'),
|
||||
),
|
||||
]
|
|
@ -37,7 +37,8 @@ class ChangeSecretRecord(JMSBaseModel):
|
|||
old_secret = fields.EncryptTextField(blank=True, null=True, verbose_name=_('Old secret'))
|
||||
new_secret = fields.EncryptTextField(blank=True, null=True, verbose_name=_('New secret'))
|
||||
date_started = models.DateTimeField(blank=True, null=True, verbose_name=_('Date started'))
|
||||
date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('Date finished'))
|
||||
date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('Date finished'), db_index=True)
|
||||
ignore_fail = models.BooleanField(default=False, verbose_name=_('Ignore fail'))
|
||||
status = models.CharField(
|
||||
max_length=16, verbose_name=_('Status'), default=ChangeSecretRecordStatusChoice.pending.value
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue