mirror of https://github.com/jumpserver/jumpserver
perf: 修改 labels 和 role 搜索
parent
1e7f268f0c
commit
1358cf532f
|
@ -59,7 +59,10 @@ class EncryptedField(serializers.CharField):
|
|||
class LabeledChoiceField(ChoiceField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LabeledChoiceField, self).__init__(*args, **kwargs)
|
||||
self.choice_mapper = {
|
||||
|
||||
@property
|
||||
def choice_mapper(self):
|
||||
return {
|
||||
key: value for key, value in self.choices.items()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,10 @@ from orgs.utils import current_org
|
|||
from rbac.models import ContentType
|
||||
from rbac.serializers import ContentTypeSerializer
|
||||
from . import serializers
|
||||
from .const import label_resource_types
|
||||
from .models import Label, LabeledResource
|
||||
|
||||
__all__ = ['LabelViewSet']
|
||||
__all__ = ['LabelViewSet', 'ContentTypeViewSet']
|
||||
|
||||
|
||||
class ContentTypeViewSet(JMSModelViewSet):
|
||||
|
@ -25,26 +26,8 @@ class ContentTypeViewSet(JMSModelViewSet):
|
|||
can_labeled_content_type = []
|
||||
model = ContentType
|
||||
|
||||
@classmethod
|
||||
def get_can_labeled_content_type_ids(cls):
|
||||
if cls.can_labeled_content_type:
|
||||
return cls.can_labeled_content_type
|
||||
content_types = ContentType.objects.all()
|
||||
for ct in content_types:
|
||||
model_cls = ct.model_class()
|
||||
if not model_cls:
|
||||
continue
|
||||
if model_cls._meta.parents:
|
||||
continue
|
||||
if 'labels' in model_cls._meta._forward_fields_map.keys():
|
||||
# if issubclass(model_cls, LabeledMixin):
|
||||
cls.can_labeled_content_type.append(ct.id)
|
||||
return cls.can_labeled_content_type
|
||||
|
||||
def get_queryset(self):
|
||||
ids = self.get_can_labeled_content_type_ids()
|
||||
queryset = ContentType.objects.filter(id__in=ids)
|
||||
return queryset
|
||||
return label_resource_types
|
||||
|
||||
@action(methods=['GET'], detail=True, serializer_class=serializers.ContentTypeResourceSerializer)
|
||||
def resources(self, request, *args, **kwargs):
|
||||
|
@ -62,6 +45,7 @@ class ContentTypeViewSet(JMSModelViewSet):
|
|||
keyword = request.query_params.get('search')
|
||||
if keyword:
|
||||
queryset = content_type.filter_queryset(queryset, keyword)
|
||||
queryset = queryset.order_by('res_type')
|
||||
return self.get_paginated_response_from_queryset(queryset)
|
||||
|
||||
|
||||
|
@ -145,3 +129,8 @@ class LabeledResourceViewSet(OrgBulkModelViewSet):
|
|||
'default': serializers.LabeledResourceSerializer,
|
||||
}
|
||||
ordering_fields = ('res_type', 'date_created')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.order_by('res_type')
|
||||
return queryset
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.functional import LazyObject
|
||||
|
||||
|
||||
class LabeledResourceType(LazyObject):
|
||||
@staticmethod
|
||||
def get_res_types():
|
||||
content_types = ContentType.objects.all()
|
||||
ids = []
|
||||
for ct in content_types:
|
||||
model_cls = ct.model_class()
|
||||
if not model_cls:
|
||||
continue
|
||||
if model_cls._meta.parents:
|
||||
continue
|
||||
if 'labels' in model_cls._meta._forward_fields_map.keys():
|
||||
ids.append(ct.id)
|
||||
return ContentType.objects.filter(id__in=ids)
|
||||
|
||||
def _setup(self):
|
||||
self._wrapped = self.get_res_types()
|
||||
|
||||
|
||||
label_resource_types = LabeledResourceType()
|
|
@ -25,7 +25,9 @@ class Label(JMSOrgBaseModel):
|
|||
|
||||
|
||||
class LabeledResource(JMSOrgBaseModel):
|
||||
label = models.ForeignKey(Label, on_delete=models.CASCADE, related_name='labeled_resources')
|
||||
label = models.ForeignKey(
|
||||
Label, on_delete=models.CASCADE, related_name='labeled_resources', verbose_name=_("Label")
|
||||
)
|
||||
res_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||
res_id = models.CharField(max_length=36, verbose_name=_("Resource ID"), db_index=True)
|
||||
resource = GenericForeignKey('res_type', 'res_id')
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Count
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.serializers.fields import ObjectRelatedField
|
||||
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from .const import label_resource_types
|
||||
from .models import Label, LabeledResource
|
||||
|
||||
__all__ = ['LabelSerializer', 'LabeledResourceSerializer', 'ContentTypeResourceSerializer']
|
||||
|
@ -27,10 +27,10 @@ class LabelSerializer(BulkOrgResourceModelSerializer):
|
|||
|
||||
|
||||
class LabeledResourceSerializer(serializers.ModelSerializer):
|
||||
res_type = ObjectRelatedField(
|
||||
queryset=ContentType.objects, attrs=('app_label', 'model', 'name'), label=_("Resource type")
|
||||
res_type = LabeledChoiceField(
|
||||
choices=[], label=_("Resource type"), source='res_type_id', required=False
|
||||
)
|
||||
label = ObjectRelatedField(queryset=Label.objects, attrs=('name', 'value'))
|
||||
label = ObjectRelatedField(queryset=Label.objects, attrs=('name', 'value'), label=_("Label"))
|
||||
resource = serializers.CharField(label=_("Resource"))
|
||||
|
||||
class Meta:
|
||||
|
@ -44,6 +44,17 @@ class LabeledResourceSerializer(serializers.ModelSerializer):
|
|||
queryset = queryset.select_related('label', 'res_type')
|
||||
return queryset
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.set_res_type_choices()
|
||||
|
||||
def set_res_type_choices(self):
|
||||
res_type_field = self.fields.get('res_type')
|
||||
if not res_type_field:
|
||||
return
|
||||
|
||||
res_type_field.choices = [(ct.id, ct.name) for ct in label_resource_types]
|
||||
|
||||
|
||||
class ContentTypeResourceSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.db.models import Count
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils._os import safe_join
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
@ -167,7 +167,7 @@ class JobExecutionViewSet(OrgBulkModelViewSet):
|
|||
|
||||
@staticmethod
|
||||
def start_deploy(instance, serializer):
|
||||
task = run_ops_job_execution.apply_async((str(instance.id),), task_id=str(instance.id))
|
||||
run_ops_job_execution.apply_async((str(instance.id),), task_id=str(instance.id))
|
||||
|
||||
def perform_create(self, serializer):
|
||||
instance = serializer.save()
|
||||
|
@ -179,7 +179,8 @@ class JobExecutionViewSet(OrgBulkModelViewSet):
|
|||
|
||||
set_task_to_serializer_data(serializer, instance.id)
|
||||
transaction.on_commit(
|
||||
lambda: run_ops_job_execution.apply_async((str(instance.id),), task_id=str(instance.id)))
|
||||
lambda: run_ops_job_execution.apply_async((str(instance.id),), task_id=str(instance.id))
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
|
|
|
@ -22,7 +22,6 @@ from acls.models import CommandFilterACL
|
|||
from assets.models import Asset
|
||||
from assets.automations.base.manager import SSHTunnelManager
|
||||
from common.db.encoder import ModelJSONFieldEncoder
|
||||
from labels.mixins import LabeledMixin
|
||||
from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner, CommandInBlackListException, UploadFileRunner
|
||||
from ops.mixin import PeriodTaskModelMixin
|
||||
from ops.variables import *
|
||||
|
@ -133,19 +132,15 @@ class JMSPermedInventory(JMSInventory):
|
|||
return mapper
|
||||
|
||||
|
||||
class Job(LabeledMixin, JMSOrgBaseModel, PeriodTaskModelMixin):
|
||||
class Job(JMSOrgBaseModel, PeriodTaskModelMixin):
|
||||
name = models.CharField(max_length=128, null=True, verbose_name=_('Name'))
|
||||
|
||||
instant = models.BooleanField(default=False)
|
||||
args = models.CharField(max_length=8192, default='', verbose_name=_('Args'), null=True, blank=True)
|
||||
module = models.CharField(max_length=128, choices=JobModules.choices, default=JobModules.shell,
|
||||
verbose_name=_('Module'),
|
||||
null=True)
|
||||
verbose_name=_('Module'), null=True)
|
||||
chdir = models.CharField(default="", max_length=1024, verbose_name=_('Chdir'), null=True, blank=True)
|
||||
timeout = models.IntegerField(default=-1, verbose_name=_('Timeout (Seconds)'))
|
||||
|
||||
playbook = models.ForeignKey('ops.Playbook', verbose_name=_("Playbook"), null=True, on_delete=models.SET_NULL)
|
||||
|
||||
type = models.CharField(max_length=128, choices=Types.choices, default=Types.adhoc, verbose_name=_("Type"))
|
||||
creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True)
|
||||
assets = models.ManyToManyField('assets.Asset', verbose_name=_("Assets"))
|
||||
|
|
|
@ -6,7 +6,6 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from private_storage.fields import PrivateFileField
|
||||
|
||||
from labels.mixins import LabeledMixin
|
||||
from ops.const import CreateMethods
|
||||
from ops.exception import PlaybookNoValidEntry
|
||||
from orgs.mixins.models import JMSOrgBaseModel
|
||||
|
@ -24,7 +23,7 @@ dangerous_keywords = (
|
|||
)
|
||||
|
||||
|
||||
class Playbook(LabeledMixin, JMSOrgBaseModel):
|
||||
class Playbook(JMSOrgBaseModel):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'), null=True)
|
||||
path = PrivateFileField(upload_to='playbooks/')
|
||||
|
|
|
@ -56,9 +56,22 @@ class RoleViewSet(JMSModelViewSet):
|
|||
return
|
||||
instance.permissions.set(clone.get_permissions())
|
||||
|
||||
def filter_builtins(self, queryset):
|
||||
keyword = self.request.query_params.get('search')
|
||||
if not keyword:
|
||||
return queryset
|
||||
|
||||
builtins = list(self.queryset.filter(builtin=True))
|
||||
matched = [role.id for role in builtins if keyword in role.display_name]
|
||||
if not matched:
|
||||
return queryset
|
||||
queryset = list(queryset.exclude(id__in=matched))
|
||||
return queryset + builtins
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = super().filter_queryset(queryset)
|
||||
queryset = queryset.order_by(*self.ordering)
|
||||
queryset = self.filter_builtins(queryset)
|
||||
return queryset
|
||||
|
||||
def set_users_amount(self, queryset):
|
||||
|
|
Loading…
Reference in New Issue