From 273d37562fc69b01f561b2ea68ebc4fb0d0db6cd Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 25 Oct 2024 10:00:15 +0800 Subject: [PATCH] perf: add date field --- apps/accounts/filters.py | 47 ++++++++++++++++++- ..._secret_account_date_discovery_and_more.py | 42 +++++++++++++++++ .../migrations/0008_account_access_by.py | 20 ++++++++ ..._remove_account_date_discovery_and_more.py | 27 +++++++++++ apps/accounts/models/account.py | 3 ++ apps/accounts/serializers/account/account.py | 13 ++--- apps/accounts/serializers/account/base.py | 13 ++--- apps/assets/const/automation.py | 1 + apps/assets/migrations/0001_initial.py | 2 +- 9 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 apps/accounts/migrations/0007_account_date_change_secret_account_date_discovery_and_more.py create mode 100644 apps/accounts/migrations/0008_account_access_by.py create mode 100644 apps/accounts/migrations/0009_remove_account_date_discovery_and_more.py diff --git a/apps/accounts/filters.py b/apps/accounts/filters.py index 622647079..a4ad3a7a7 100644 --- a/apps/accounts/filters.py +++ b/apps/accounts/filters.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # from django.db.models import Q +from django.utils import timezone from django_filters import rest_framework as drf_filters from assets.models import Node @@ -22,15 +23,57 @@ class AccountFilterSet(BaseFilterSet): platform = drf_filters.CharFilter(field_name='asset__platform_id', lookup_expr='exact') category = drf_filters.CharFilter(field_name='asset__platform__category', lookup_expr='exact') type = drf_filters.CharFilter(field_name='asset__platform__type', lookup_expr='exact') + latest_discovery = drf_filters.BooleanFilter(method='filter_latest') + latest_accessed = drf_filters.BooleanFilter(method='filter_latest') + 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') + is_zombie = drf_filters.BooleanFilter(method='filter_risk',) + is_ghost = drf_filters.BooleanFilter(method='filter_risk',) + is_weak_password = drf_filters.BooleanFilter(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') @staticmethod def filter_has_secret(queryset, name, has_secret): - q = Q(secret__isnull=True) | Q(secret='') + q = Q(_secret__isnull=True) | Q(_secret='') if has_secret: return queryset.exclude(q) else: return queryset.filter(q) + @staticmethod + def filter_long_time(queryset, name, value): + return queryset + + @staticmethod + def filter_risk(queryset, name, value): + return queryset + + @staticmethod + def filter_latest(queryset, name, value): + if not value: + return queryset + + date = timezone.now() - timezone.timedelta(days=7) + kwargs = {} + + if name == 'latest_discovery': + kwargs.update({'date_created__gte': date, 'source': 'collected'}) + elif name == 'latest_accessed': + kwargs.update({'date_last_access__gte': date}) + elif name == 'latest_updated': + kwargs.update({'date_updated__gte': date}) + elif name == 'latest_secret_changed': + kwargs.update({'date_change_secret__gt': date}) + + if name == 'latest_secret_change_failed': + queryset = queryset.filter(date_change_secret__gt=date).exclude(change_secret_status='ok') + + if kwargs: + queryset = queryset.filter(date_last_access__gte=date) + return queryset + @staticmethod def filter_nodes(queryset, name, value): nodes = Node.objects.filter(id=value) @@ -46,7 +89,7 @@ class AccountFilterSet(BaseFilterSet): class Meta: model = Account - fields = ['id', 'asset', 'source_id', 'secret_type'] + fields = ['id', 'asset', 'source_id', 'secret_type', 'category', 'type'] class GatheredAccountFilterSet(BaseFilterSet): diff --git a/apps/accounts/migrations/0007_account_date_change_secret_account_date_discovery_and_more.py b/apps/accounts/migrations/0007_account_date_change_secret_account_date_discovery_and_more.py new file mode 100644 index 000000000..54249439c --- /dev/null +++ b/apps/accounts/migrations/0007_account_date_change_secret_account_date_discovery_and_more.py @@ -0,0 +1,42 @@ +# Generated by Django 4.1.13 on 2024-10-24 07:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0006_accountcheckautomation_accountrisk"), + ] + + operations = [ + migrations.AddField( + model_name="account", + name="date_change_secret", + field=models.DateTimeField( + blank=True, null=True, verbose_name="Date change secret" + ), + ), + migrations.AddField( + model_name="account", + name="date_discovery", + field=models.DateTimeField( + blank=True, null=True, verbose_name="Date discovery" + ), + ), + migrations.AlterField( + model_name="account", + name="connectivity", + field=models.CharField( + choices=[ + ("-", "Unknown"), + ("na", "N/A"), + ("ok", "OK"), + ("err", "Error"), + ], + default="-", + max_length=16, + verbose_name="Connectivity", + ), + ), + ] diff --git a/apps/accounts/migrations/0008_account_access_by.py b/apps/accounts/migrations/0008_account_access_by.py new file mode 100644 index 000000000..f7f202ba0 --- /dev/null +++ b/apps/accounts/migrations/0008_account_access_by.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.13 on 2024-10-24 08:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0007_account_date_change_secret_account_date_discovery_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="account", + name="access_by", + field=models.CharField( + blank=True, max_length=128, null=True, verbose_name="Access by" + ), + ), + ] diff --git a/apps/accounts/migrations/0009_remove_account_date_discovery_and_more.py b/apps/accounts/migrations/0009_remove_account_date_discovery_and_more.py new file mode 100644 index 000000000..2a6352577 --- /dev/null +++ b/apps/accounts/migrations/0009_remove_account_date_discovery_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.1.13 on 2024-10-24 08:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0008_account_access_by"), + ] + + operations = [ + migrations.RemoveField( + model_name="account", + name="date_discovery", + ), + migrations.AddField( + model_name="account", + name="change_secret_status", + field=models.CharField( + blank=True, + max_length=16, + null=True, + verbose_name="Change secret status", + ), + ), + ] diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index d25dcaedd..70c4b537c 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -58,6 +58,9 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount): source = models.CharField(max_length=30, default=Source.LOCAL, verbose_name=_('Source')) source_id = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Source ID')) date_last_access = models.DateTimeField(null=True, blank=True, verbose_name=_('Date last access')) + access_by = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Access by')) + date_change_secret = models.DateTimeField(null=True, blank=True, verbose_name=_('Date change secret')) + change_secret_status = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Change secret status')) class Meta: verbose_name = _('Account') diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 3b59bb6a7..27e3f8303 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -235,14 +235,15 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize class Meta(BaseAccountSerializer.Meta): model = Account + automation_fields = [ + 'date_last_access', 'access_by', 'date_verified', 'connectivity', + 'date_change_secret', 'change_secret_status' + ] fields = BaseAccountSerializer.Meta.fields + [ 'su_from', 'asset', 'version', - 'source', 'source_id', 'connectivity', - 'secret_reset', - ] + AccountCreateUpdateSerializerMixin.Meta.fields - read_only_fields = BaseAccountSerializer.Meta.read_only_fields + [ - 'connectivity' - ] + 'source', 'source_id', 'secret_reset', + ] + AccountCreateUpdateSerializerMixin.Meta.fields + automation_fields + read_only_fields = BaseAccountSerializer.Meta.read_only_fields + automation_fields extra_kwargs = { **BaseAccountSerializer.Meta.extra_kwargs, 'name': {'required': False}, diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index 7340b09df..a6eacd83b 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -74,20 +74,13 @@ class BaseAccountSerializer( model = BaseAccount fields_mini = ["id", "name", "username"] fields_small = fields_mini + [ - "secret_type", - "secret", - "passphrase", - "privileged", - "is_active", - "spec_info", + "secret_type", "secret", "passphrase", + "privileged", "is_active", "spec_info", ] fields_other = ["created_by", "date_created", "date_updated", "comment"] fields = fields_small + fields_other + ["labels"] read_only_fields = [ - "spec_info", - "date_verified", - "created_by", - "date_created", + "spec_info", "created_by", "date_created", ] extra_kwargs = { "spec_info": {"label": _("Spec info")}, diff --git a/apps/assets/const/automation.py b/apps/assets/const/automation.py index 135102312..e70387cfe 100644 --- a/apps/assets/const/automation.py +++ b/apps/assets/const/automation.py @@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _ class Connectivity(TextChoices): UNKNOWN = '-', _('Unknown') + NA = 'na', _('N/A') OK = 'ok', _('OK') ERR = 'err', _('Error') diff --git a/apps/assets/migrations/0001_initial.py b/apps/assets/migrations/0001_initial.py index 1efb07ebb..63133bbc2 100644 --- a/apps/assets/migrations/0001_initial.py +++ b/apps/assets/migrations/0001_initial.py @@ -28,7 +28,7 @@ class Migration(migrations.Migration): ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'OK'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('na', 'N/A'), ('ok', 'OK'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('address', models.CharField(db_index=True, max_length=767, verbose_name='Address')),