mirror of https://github.com/jumpserver/jumpserver
Merge branch 'pam' into pr@pam@translate
commit
84cbe1c644
|
@ -7,35 +7,43 @@ 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
|
||||
from .models import Account, GatheredAccount, ChangeSecretRecord, AccountRisk
|
||||
|
||||
|
||||
class AccountFilterSet(BaseFilterSet):
|
||||
ip = drf_filters.CharFilter(field_name='address', lookup_expr='exact')
|
||||
hostname = drf_filters.CharFilter(field_name='name', lookup_expr='exact')
|
||||
username = drf_filters.CharFilter(field_name="username", lookup_expr='exact')
|
||||
address = drf_filters.CharFilter(field_name="asset__address", lookup_expr='exact')
|
||||
asset_id = drf_filters.CharFilter(field_name="asset", lookup_expr='exact')
|
||||
asset = drf_filters.CharFilter(field_name='asset', lookup_expr='exact')
|
||||
assets = drf_filters.CharFilter(field_name='asset_id', lookup_expr='exact')
|
||||
nodes = drf_filters.CharFilter(method='filter_nodes')
|
||||
node_id = drf_filters.CharFilter(method='filter_nodes')
|
||||
has_secret = drf_filters.BooleanFilter(method='filter_has_secret')
|
||||
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')
|
||||
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')
|
||||
ip = drf_filters.CharFilter(field_name="address", lookup_expr="exact")
|
||||
hostname = drf_filters.CharFilter(field_name="name", lookup_expr="exact")
|
||||
username = drf_filters.CharFilter(field_name="username", lookup_expr="exact")
|
||||
address = drf_filters.CharFilter(field_name="asset__address", lookup_expr="exact")
|
||||
asset_id = drf_filters.CharFilter(field_name="asset", lookup_expr="exact")
|
||||
asset = drf_filters.CharFilter(field_name="asset", lookup_expr="exact")
|
||||
assets = drf_filters.CharFilter(field_name="asset_id", lookup_expr="exact")
|
||||
nodes = drf_filters.CharFilter(method="filter_nodes")
|
||||
node_id = drf_filters.CharFilter(method="filter_nodes")
|
||||
has_secret = drf_filters.BooleanFilter(method="filter_has_secret")
|
||||
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")
|
||||
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")
|
||||
|
||||
@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:
|
||||
|
@ -45,15 +53,15 @@ class AccountFilterSet(BaseFilterSet):
|
|||
def filter_long_time(queryset, name, value):
|
||||
date = timezone.now() - timezone.timedelta(days=30)
|
||||
|
||||
if name == 'long_time_no_change_secret':
|
||||
field = 'date_change_secret'
|
||||
confirm_field = 'change_secret_status'
|
||||
if name == "long_time_no_change_secret":
|
||||
field = "date_change_secret"
|
||||
confirm_field = "change_secret_status"
|
||||
else:
|
||||
field = 'date_verified'
|
||||
confirm_field = 'connectivity'
|
||||
field = "date_verified"
|
||||
confirm_field = "connectivity"
|
||||
|
||||
q = Q(**{f'{field}__lt': date}) | Q(**{f'{field}__isnull': True})
|
||||
confirm_q = {f'{confirm_field}': 'na'}
|
||||
q = Q(**{f"{field}__lt": date}) | Q(**{f"{field}__isnull": True})
|
||||
confirm_q = {f"{confirm_field}": "na"}
|
||||
queryset = queryset.exclude(**confirm_q).filter(q)
|
||||
return queryset
|
||||
|
||||
|
@ -62,7 +70,11 @@ class AccountFilterSet(BaseFilterSet):
|
|||
if not value:
|
||||
return queryset
|
||||
|
||||
return Account.get_risks(queryset, value)
|
||||
risks = AccountRisk.objects.filter(risk=value)
|
||||
usernames = risks.values_list('username', flat=True)
|
||||
assets = risks.values_list('asset', flat=True)
|
||||
queryset = queryset.filter(username__in=usernames, asset__in=assets)
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def filter_latest(queryset, name, value):
|
||||
|
@ -72,17 +84,19 @@ class AccountFilterSet(BaseFilterSet):
|
|||
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_login__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_discovery":
|
||||
kwargs.update({"date_created__gte": date, "source": "collected"})
|
||||
elif name == "latest_accessed":
|
||||
kwargs.update({"date_last_login__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 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_login__gte=date)
|
||||
|
@ -97,19 +111,22 @@ class AccountFilterSet(BaseFilterSet):
|
|||
node_qs = Node.objects.none()
|
||||
for node in nodes:
|
||||
node_qs |= node.get_all_children(with_self=True)
|
||||
node_ids = list(node_qs.values_list('id', flat=True))
|
||||
node_ids = list(node_qs.values_list("id", flat=True))
|
||||
queryset = queryset.filter(asset__nodes__in=node_ids)
|
||||
return queryset
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['id', 'asset', 'source_id', 'secret_type', 'category', 'type']
|
||||
fields = ["id", "asset", "source_id", "secret_type", "category", "type"]
|
||||
|
||||
|
||||
class GatheredAccountFilterSet(BaseFilterSet):
|
||||
node_id = drf_filters.CharFilter(method='filter_nodes')
|
||||
asset_id = drf_filters.CharFilter(field_name='asset_id', lookup_expr='exact')
|
||||
asset_name = drf_filters.CharFilter(field_name='asset__name', lookup_expr='icontains')
|
||||
node_id = drf_filters.CharFilter(method="filter_nodes")
|
||||
asset_id = drf_filters.CharFilter(field_name="asset_id", lookup_expr="exact")
|
||||
asset_name = drf_filters.CharFilter(
|
||||
field_name="asset__name", lookup_expr="icontains"
|
||||
)
|
||||
status = drf_filters.CharFilter(field_name="status", lookup_expr="exact")
|
||||
|
||||
@staticmethod
|
||||
def filter_nodes(queryset, name, value):
|
||||
|
@ -117,15 +134,20 @@ class GatheredAccountFilterSet(BaseFilterSet):
|
|||
|
||||
class Meta:
|
||||
model = GatheredAccount
|
||||
fields = ['id', 'username']
|
||||
fields = ["id", "username"]
|
||||
|
||||
|
||||
class ChangeSecretRecordFilterSet(BaseFilterSet):
|
||||
asset_name = drf_filters.CharFilter(field_name='asset__name', lookup_expr='icontains')
|
||||
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')
|
||||
asset_name = drf_filters.CharFilter(
|
||||
field_name="asset__name", lookup_expr="icontains"
|
||||
)
|
||||
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):
|
||||
|
@ -138,4 +160,4 @@ class ChangeSecretRecordFilterSet(BaseFilterSet):
|
|||
|
||||
class Meta:
|
||||
model = ChangeSecretRecord
|
||||
fields = ['id', 'status', 'asset_id', 'execution']
|
||||
fields = ["id", "status", "asset_id", "execution"]
|
||||
|
|
|
@ -230,7 +230,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, ResourceLabelsMixin, Writa
|
|||
.prefetch_related('platform', 'platform__automation') \
|
||||
.annotate(category=F("platform__category")) \
|
||||
.annotate(type=F("platform__type")) \
|
||||
.annotate(assets_amount=Count('accounts'))
|
||||
.annotate(accounts_amount=Count('accounts'))
|
||||
if queryset.model is Asset:
|
||||
queryset = queryset.prefetch_related('labels__label', 'labels')
|
||||
else:
|
||||
|
|
|
@ -6,7 +6,8 @@ from rest_framework.validators import UniqueValidator
|
|||
from assets.models import Asset
|
||||
from common.serializers import (
|
||||
WritableNestedModelSerializer, type_field_map, MethodSerializer,
|
||||
DictSerializer, create_serializer_class, ResourceLabelsMixin
|
||||
DictSerializer, create_serializer_class, ResourceLabelsMixin,
|
||||
CommonSerializerMixin
|
||||
)
|
||||
from common.serializers.fields import LabeledChoiceField, ObjectRelatedField
|
||||
from common.utils import lazyproperty
|
||||
|
@ -158,7 +159,7 @@ class PlatformCustomField(serializers.Serializer):
|
|||
choices = serializers.ListField(default=list, label=_("Choices"), required=False)
|
||||
|
||||
|
||||
class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
|
||||
class PlatformSerializer(ResourceLabelsMixin, CommonSerializerMixin, WritableNestedModelSerializer):
|
||||
id = serializers.IntegerField(
|
||||
label='ID', required=False,
|
||||
validators=[UniqueValidator(queryset=Platform.objects.all())]
|
||||
|
|
|
@ -402,6 +402,14 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
{% if demo_mode %}
|
||||
<div>
|
||||
<p class="red-fonts" style='text-align: center;'>
|
||||
{% trans 'Username' %}: demo {% trans 'Password' %}: jumpserver
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="more-login">
|
||||
{% if auth_methods %}
|
||||
<div class="more-methods-title {{ current_lang.code }}">
|
||||
|
|
|
@ -4,6 +4,7 @@ import base64
|
|||
import json
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
from django.utils import timezone
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
@ -18,18 +19,26 @@ from rest_framework.filters import OrderingFilter
|
|||
from common import const
|
||||
from common.db.fields import RelatedManager
|
||||
|
||||
logger = logging.getLogger('jumpserver.common')
|
||||
logger = logging.getLogger("jumpserver.common")
|
||||
|
||||
__all__ = [
|
||||
"DatetimeRangeFilterBackend", "IDSpmFilterBackend",
|
||||
'IDInFilterBackend', "CustomFilterBackend",
|
||||
"BaseFilterSet", 'IDNotFilterBackend',
|
||||
'NotOrRelFilterBackend', 'LabelFilterBackend',
|
||||
'RewriteOrderingFilter', 'AttrRulesFilterBackend'
|
||||
"DatetimeRangeFilterBackend",
|
||||
"IDSpmFilterBackend",
|
||||
"IDInFilterBackend",
|
||||
"CustomFilterBackend",
|
||||
"BaseFilterSet",
|
||||
"IDNotFilterBackend",
|
||||
"NotOrRelFilterBackend",
|
||||
"LabelFilterBackend",
|
||||
"RewriteOrderingFilter",
|
||||
"AttrRulesFilterBackend",
|
||||
]
|
||||
|
||||
|
||||
class BaseFilterSet(drf_filters.FilterSet):
|
||||
days = drf_filters.NumberFilter(method="filter_days")
|
||||
days__lt = drf_filters.NumberFilter(method="filter_days")
|
||||
|
||||
def do_nothing(self, queryset, name, value):
|
||||
return queryset
|
||||
|
||||
|
@ -38,6 +47,22 @@ class BaseFilterSet(drf_filters.FilterSet):
|
|||
return self.form.cleaned_data[k]
|
||||
return default
|
||||
|
||||
@staticmethod
|
||||
def filter_days(queryset, name, value):
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
return queryset.none()
|
||||
|
||||
if name == 'days':
|
||||
arg = 'date_created__gte'
|
||||
else:
|
||||
arg = 'date_created__lt'
|
||||
|
||||
date = timezone.now() - timezone.timedelta(days=value)
|
||||
kwargs = {arg: date}
|
||||
return queryset.filter(**kwargs)
|
||||
|
||||
|
||||
class DatetimeRangeFilterBackend(filters.BaseFilterBackend):
|
||||
def get_schema_fields(self, view):
|
||||
|
@ -50,18 +75,20 @@ class DatetimeRangeFilterBackend(filters.BaseFilterBackend):
|
|||
for v in date_range_keyword:
|
||||
ret.append(
|
||||
coreapi.Field(
|
||||
name=v, location='query', required=False, type='string',
|
||||
name=v,
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
schema=coreschema.String(
|
||||
title=v,
|
||||
description='%s %s' % (attr, v)
|
||||
)
|
||||
title=v, description="%s %s" % (attr, v)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
def _get_date_range_filter_fields(self, view):
|
||||
if not hasattr(view, 'date_range_filter_fields'):
|
||||
if not hasattr(view, "date_range_filter_fields"):
|
||||
return {}
|
||||
try:
|
||||
return dict(view.date_range_filter_fields)
|
||||
|
@ -75,7 +102,9 @@ class DatetimeRangeFilterBackend(filters.BaseFilterBackend):
|
|||
('db column', ('query param date from', 'query param date to'))
|
||||
]
|
||||
```
|
||||
""".format(view.name)
|
||||
""".format(
|
||||
view.name
|
||||
)
|
||||
logger.error(msg)
|
||||
raise ImproperlyConfigured(msg)
|
||||
|
||||
|
@ -110,14 +139,17 @@ class IDSpmFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='spm', location='query', required=False,
|
||||
type='string', example='',
|
||||
description='Pre post objects id get spm id, then using filter'
|
||||
name="spm",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="",
|
||||
description="Pre post objects id get spm id, then using filter",
|
||||
)
|
||||
]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
spm = request.query_params.get('spm')
|
||||
spm = request.query_params.get("spm")
|
||||
if not spm:
|
||||
return queryset
|
||||
cache_key = const.KEY_CACHE_RESOURCE_IDS.format(spm)
|
||||
|
@ -127,7 +159,7 @@ class IDSpmFilterBackend(filters.BaseFilterBackend):
|
|||
return queryset.none()
|
||||
if isinstance(resource_ids, str):
|
||||
resource_ids = [resource_ids]
|
||||
if hasattr(view, 'filter_spm_queryset'):
|
||||
if hasattr(view, "filter_spm_queryset"):
|
||||
queryset = view.filter_spm_queryset(resource_ids, queryset)
|
||||
else:
|
||||
queryset = queryset.filter(id__in=resource_ids)
|
||||
|
@ -138,17 +170,20 @@ class IDInFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='ids', location='query', required=False,
|
||||
type='string', example='/api/v1/users/users?ids=1,2,3',
|
||||
description='Filter by id set'
|
||||
name="ids",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="/api/v1/users/users?ids=1,2,3",
|
||||
description="Filter by id set",
|
||||
)
|
||||
]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
ids = request.query_params.get('ids')
|
||||
ids = request.query_params.get("ids")
|
||||
if not ids:
|
||||
return queryset
|
||||
id_list = [i.strip() for i in ids.split(',')]
|
||||
id_list = [i.strip() for i in ids.split(",")]
|
||||
queryset = queryset.filter(id__in=id_list)
|
||||
return queryset
|
||||
|
||||
|
@ -157,17 +192,20 @@ class IDNotFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='id!', location='query', required=False,
|
||||
type='string', example='/api/v1/users/users?id!=1,2,3',
|
||||
description='Exclude by id set'
|
||||
name="id!",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="/api/v1/users/users?id!=1,2,3",
|
||||
description="Exclude by id set",
|
||||
)
|
||||
]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
ids = request.query_params.get('id!')
|
||||
ids = request.query_params.get("id!")
|
||||
if not ids:
|
||||
return queryset
|
||||
id_list = [i.strip() for i in ids.split(',')]
|
||||
id_list = [i.strip() for i in ids.split(",")]
|
||||
queryset = queryset.exclude(id__in=id_list)
|
||||
return queryset
|
||||
|
||||
|
@ -176,26 +214,30 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='label', location='query', required=False,
|
||||
type='string', example='/api/v1/users/users?label=abc',
|
||||
description='Filter by label'
|
||||
name="label",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="/api/v1/users/users?label=abc",
|
||||
description="Filter by label",
|
||||
)
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def parse_labels(labels_id):
|
||||
from labels.models import Label
|
||||
label_ids = [i.strip() for i in labels_id.split(',')]
|
||||
|
||||
label_ids = [i.strip() for i in labels_id.split(",")]
|
||||
cleaned = []
|
||||
|
||||
args = []
|
||||
for label_id in label_ids:
|
||||
kwargs = {}
|
||||
if ':' in label_id:
|
||||
k, v = label_id.split(':', 1)
|
||||
kwargs['name'] = k.strip()
|
||||
if v != '*':
|
||||
kwargs['value'] = v.strip()
|
||||
if ":" in label_id:
|
||||
k, v = label_id.split(":", 1)
|
||||
kwargs["name"] = k.strip()
|
||||
if v != "*":
|
||||
kwargs["value"] = v.strip()
|
||||
args.append(kwargs)
|
||||
else:
|
||||
cleaned.append(label_id)
|
||||
|
@ -209,14 +251,14 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
|||
return cleaned
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
labels_id = request.query_params.get('labels')
|
||||
labels_id = request.query_params.get("labels")
|
||||
if not labels_id:
|
||||
return queryset
|
||||
|
||||
if not hasattr(queryset, 'model'):
|
||||
if not hasattr(queryset, "model"):
|
||||
return queryset
|
||||
|
||||
if not hasattr(queryset.model, 'label_model'):
|
||||
if not hasattr(queryset.model, "label_model"):
|
||||
return queryset
|
||||
|
||||
model = queryset.model.label_model()
|
||||
|
@ -225,7 +267,8 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
|||
model_name = model._meta.model_name
|
||||
|
||||
full_resources = labeled_resource_cls.objects.filter(
|
||||
res_type__app_label=app_label, res_type__model=model_name,
|
||||
res_type__app_label=app_label,
|
||||
res_type__model=model_name,
|
||||
)
|
||||
labels = self.parse_labels(labels_id)
|
||||
grouped = defaultdict(set)
|
||||
|
@ -234,8 +277,10 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
|||
|
||||
matched_ids = set()
|
||||
for name, label_ids in grouped.items():
|
||||
resources = model.filter_resources_by_labels(full_resources, label_ids, rel='any')
|
||||
res_ids = resources.values_list('res_id', flat=True)
|
||||
resources = model.filter_resources_by_labels(
|
||||
full_resources, label_ids, rel="any"
|
||||
)
|
||||
res_ids = resources.values_list("res_id", flat=True)
|
||||
if not matched_ids:
|
||||
matched_ids = set(res_ids)
|
||||
else:
|
||||
|
@ -249,16 +294,14 @@ class CustomFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
fields = []
|
||||
defaults = dict(
|
||||
location='query', required=False,
|
||||
type='string', example='',
|
||||
description=''
|
||||
location="query", required=False, type="string", example="", description=""
|
||||
)
|
||||
if not hasattr(view, 'custom_filter_fields'):
|
||||
if not hasattr(view, "custom_filter_fields"):
|
||||
return []
|
||||
|
||||
for field in view.custom_filter_fields:
|
||||
if isinstance(field, str):
|
||||
defaults['name'] = field
|
||||
defaults["name"] = field
|
||||
elif isinstance(field, dict):
|
||||
defaults.update(field)
|
||||
else:
|
||||
|
@ -270,7 +313,7 @@ class CustomFilterBackend(filters.BaseFilterBackend):
|
|||
return queryset
|
||||
|
||||
|
||||
def current_user_filter(user_field='user'):
|
||||
def current_user_filter(user_field="user"):
|
||||
class CurrentUserFilter(filters.BaseFilterBackend):
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
return queryset.filter(**{user_field: request.user})
|
||||
|
@ -290,27 +333,30 @@ class AttrRulesFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='attr_rules', location='query', required=False,
|
||||
type='string', example='/api/v1/users/users?attr_rules=jsonbase64',
|
||||
description='Filter by json like {"type": "attrs", "attrs": []} to base64'
|
||||
name="attr_rules",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="/api/v1/users/users?attr_rules=jsonbase64",
|
||||
description='Filter by json like {"type": "attrs", "attrs": []} to base64',
|
||||
)
|
||||
]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
attr_rules = request.query_params.get('attr_rules')
|
||||
attr_rules = request.query_params.get("attr_rules")
|
||||
if not attr_rules:
|
||||
return queryset
|
||||
|
||||
try:
|
||||
attr_rules = base64.b64decode(attr_rules.encode('utf-8'))
|
||||
attr_rules = base64.b64decode(attr_rules.encode("utf-8"))
|
||||
except Exception:
|
||||
raise ValidationError({'attr_rules': 'attr_rules should be base64'})
|
||||
raise ValidationError({"attr_rules": "attr_rules should be base64"})
|
||||
try:
|
||||
attr_rules = json.loads(attr_rules)
|
||||
except Exception:
|
||||
raise ValidationError({'attr_rules': 'attr_rules should be json'})
|
||||
raise ValidationError({"attr_rules": "attr_rules should be json"})
|
||||
|
||||
logger.debug('attr_rules: %s', attr_rules)
|
||||
logger.debug("attr_rules: %s", attr_rules)
|
||||
qs = RelatedManager.get_to_filter_qs(attr_rules, queryset.model)
|
||||
for q in qs:
|
||||
queryset = queryset.filter(q)
|
||||
|
@ -321,33 +367,38 @@ class NotOrRelFilterBackend(filters.BaseFilterBackend):
|
|||
def get_schema_fields(self, view):
|
||||
return [
|
||||
coreapi.Field(
|
||||
name='_rel', location='query', required=False,
|
||||
type='string', example='/api/v1/users/users?name=abc&username=def&_rel=union',
|
||||
description='Filter by rel, or not, default is and'
|
||||
name="_rel",
|
||||
location="query",
|
||||
required=False,
|
||||
type="string",
|
||||
example="/api/v1/users/users?name=abc&username=def&_rel=union",
|
||||
description="Filter by rel, or not, default is and",
|
||||
)
|
||||
]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
_rel = request.query_params.get('_rel')
|
||||
if not _rel or _rel not in ('or', 'not'):
|
||||
_rel = request.query_params.get("_rel")
|
||||
if not _rel or _rel not in ("or", "not"):
|
||||
return queryset
|
||||
if _rel == 'not':
|
||||
if _rel == "not":
|
||||
queryset.query.where.negated = True
|
||||
elif _rel == 'or':
|
||||
queryset.query.where.connector = 'OR'
|
||||
elif _rel == "or":
|
||||
queryset.query.where.connector = "OR"
|
||||
queryset._result_cache = None
|
||||
return queryset
|
||||
|
||||
|
||||
class RewriteOrderingFilter(OrderingFilter):
|
||||
default_ordering_if_has = ('name', )
|
||||
default_ordering_if_has = ("name",)
|
||||
|
||||
def get_default_ordering(self, view):
|
||||
ordering = super().get_default_ordering(view)
|
||||
# 如果 view.ordering = [] 表示不排序, 这样可以节约性能 (比如: 用户授权的资产)
|
||||
if ordering is not None:
|
||||
return ordering
|
||||
ordering_fields = getattr(view, 'ordering_fields', self.ordering_fields)
|
||||
ordering_fields = getattr(view, "ordering_fields", self.ordering_fields)
|
||||
if ordering_fields:
|
||||
ordering = tuple([f for f in ordering_fields if f in self.default_ordering_if_has])
|
||||
ordering = tuple(
|
||||
[f for f in ordering_fields if f in self.default_ordering_if_has]
|
||||
)
|
||||
return ordering
|
||||
|
|
|
@ -5254,7 +5254,7 @@ msgstr ""
|
|||
|
||||
#: ops/models/job.py:148
|
||||
msgid "Timeout (Seconds)"
|
||||
msgstr ""
|
||||
msgstr "Timeout (Sec)"
|
||||
|
||||
#: ops/models/job.py:153
|
||||
msgid "Use Parameter Define"
|
||||
|
@ -5334,8 +5334,8 @@ msgid "Next execution time"
|
|||
msgstr ""
|
||||
|
||||
#: ops/serializers/job.py:15
|
||||
msgid "Execute after saving"
|
||||
msgstr "Execute after saving"
|
||||
msgid "Run on save"
|
||||
msgstr "Run on save"
|
||||
|
||||
#: ops/serializers/job.py:72
|
||||
msgid "Job type"
|
||||
|
|
|
@ -5527,7 +5527,7 @@ msgid "Next execution time"
|
|||
msgstr "最後の実行"
|
||||
|
||||
#: ops/serializers/job.py:15
|
||||
msgid "Execute after saving"
|
||||
msgid "Run on save"
|
||||
msgstr "保存後に実行"
|
||||
|
||||
#: ops/serializers/job.py:72
|
||||
|
|
|
@ -5478,7 +5478,7 @@ msgid "Next execution time"
|
|||
msgstr "下次执行时间"
|
||||
|
||||
#: ops/serializers/job.py:15
|
||||
msgid "Execute after saving"
|
||||
msgid "Run on save"
|
||||
msgstr "保存后执行"
|
||||
|
||||
#: ops/serializers/job.py:72
|
||||
|
|
|
@ -12,7 +12,7 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
|||
|
||||
class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin):
|
||||
creator = ReadableHiddenField(default=serializers.CurrentUserDefault())
|
||||
run_after_save = serializers.BooleanField(label=_("Execute after saving"), default=False, required=False)
|
||||
run_after_save = serializers.BooleanField(label=_("Run on save"), default=False, required=False)
|
||||
nodes = serializers.ListField(required=False, child=serializers.CharField())
|
||||
date_last_run = serializers.DateTimeField(label=_('Date last run'), read_only=True)
|
||||
name = serializers.CharField(label=_('Name'), max_length=128, allow_blank=True, required=False)
|
||||
|
|
Loading…
Reference in New Issue