mirror of https://github.com/jumpserver/jumpserver
perf: add date field
parent
90cbb4be23
commit
273d37562f
|
@ -1,6 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.utils import timezone
|
||||||
from django_filters import rest_framework as drf_filters
|
from django_filters import rest_framework as drf_filters
|
||||||
|
|
||||||
from assets.models import Node
|
from assets.models import Node
|
||||||
|
@ -22,15 +23,57 @@ class AccountFilterSet(BaseFilterSet):
|
||||||
platform = drf_filters.CharFilter(field_name='asset__platform_id', lookup_expr='exact')
|
platform = drf_filters.CharFilter(field_name='asset__platform_id', lookup_expr='exact')
|
||||||
category = drf_filters.CharFilter(field_name='asset__platform__category', 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')
|
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
|
@staticmethod
|
||||||
def filter_has_secret(queryset, name, has_secret):
|
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:
|
if has_secret:
|
||||||
return queryset.exclude(q)
|
return queryset.exclude(q)
|
||||||
else:
|
else:
|
||||||
return queryset.filter(q)
|
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
|
@staticmethod
|
||||||
def filter_nodes(queryset, name, value):
|
def filter_nodes(queryset, name, value):
|
||||||
nodes = Node.objects.filter(id=value)
|
nodes = Node.objects.filter(id=value)
|
||||||
|
@ -46,7 +89,7 @@ class AccountFilterSet(BaseFilterSet):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ['id', 'asset', 'source_id', 'secret_type']
|
fields = ['id', 'asset', 'source_id', 'secret_type', 'category', 'type']
|
||||||
|
|
||||||
|
|
||||||
class GatheredAccountFilterSet(BaseFilterSet):
|
class GatheredAccountFilterSet(BaseFilterSet):
|
||||||
|
|
|
@ -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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -58,6 +58,9 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount):
|
||||||
source = models.CharField(max_length=30, default=Source.LOCAL, verbose_name=_('Source'))
|
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'))
|
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'))
|
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:
|
class Meta:
|
||||||
verbose_name = _('Account')
|
verbose_name = _('Account')
|
||||||
|
|
|
@ -235,14 +235,15 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize
|
||||||
|
|
||||||
class Meta(BaseAccountSerializer.Meta):
|
class Meta(BaseAccountSerializer.Meta):
|
||||||
model = Account
|
model = Account
|
||||||
|
automation_fields = [
|
||||||
|
'date_last_access', 'access_by', 'date_verified', 'connectivity',
|
||||||
|
'date_change_secret', 'change_secret_status'
|
||||||
|
]
|
||||||
fields = BaseAccountSerializer.Meta.fields + [
|
fields = BaseAccountSerializer.Meta.fields + [
|
||||||
'su_from', 'asset', 'version',
|
'su_from', 'asset', 'version',
|
||||||
'source', 'source_id', 'connectivity',
|
'source', 'source_id', 'secret_reset',
|
||||||
'secret_reset',
|
] + AccountCreateUpdateSerializerMixin.Meta.fields + automation_fields
|
||||||
] + AccountCreateUpdateSerializerMixin.Meta.fields
|
read_only_fields = BaseAccountSerializer.Meta.read_only_fields + automation_fields
|
||||||
read_only_fields = BaseAccountSerializer.Meta.read_only_fields + [
|
|
||||||
'connectivity'
|
|
||||||
]
|
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
**BaseAccountSerializer.Meta.extra_kwargs,
|
**BaseAccountSerializer.Meta.extra_kwargs,
|
||||||
'name': {'required': False},
|
'name': {'required': False},
|
||||||
|
|
|
@ -74,20 +74,13 @@ class BaseAccountSerializer(
|
||||||
model = BaseAccount
|
model = BaseAccount
|
||||||
fields_mini = ["id", "name", "username"]
|
fields_mini = ["id", "name", "username"]
|
||||||
fields_small = fields_mini + [
|
fields_small = fields_mini + [
|
||||||
"secret_type",
|
"secret_type", "secret", "passphrase",
|
||||||
"secret",
|
"privileged", "is_active", "spec_info",
|
||||||
"passphrase",
|
|
||||||
"privileged",
|
|
||||||
"is_active",
|
|
||||||
"spec_info",
|
|
||||||
]
|
]
|
||||||
fields_other = ["created_by", "date_created", "date_updated", "comment"]
|
fields_other = ["created_by", "date_created", "date_updated", "comment"]
|
||||||
fields = fields_small + fields_other + ["labels"]
|
fields = fields_small + fields_other + ["labels"]
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
"spec_info",
|
"spec_info", "created_by", "date_created",
|
||||||
"date_verified",
|
|
||||||
"created_by",
|
|
||||||
"date_created",
|
|
||||||
]
|
]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
"spec_info": {"label": _("Spec info")},
|
"spec_info": {"label": _("Spec info")},
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
class Connectivity(TextChoices):
|
class Connectivity(TextChoices):
|
||||||
UNKNOWN = '-', _('Unknown')
|
UNKNOWN = '-', _('Unknown')
|
||||||
|
NA = 'na', _('N/A')
|
||||||
OK = 'ok', _('OK')
|
OK = 'ok', _('OK')
|
||||||
ERR = 'err', _('Error')
|
ERR = 'err', _('Error')
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Migration(migrations.Migration):
|
||||||
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
|
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
|
||||||
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
('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')),
|
('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')),
|
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
|
||||||
('name', models.CharField(max_length=128, verbose_name='Name')),
|
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||||
('address', models.CharField(db_index=True, max_length=767, verbose_name='Address')),
|
('address', models.CharField(db_index=True, max_length=767, verbose_name='Address')),
|
||||||
|
|
Loading…
Reference in New Issue