* perf: 优化 suggesstion

* perf: 修改 migrations
pull/7694/head
老广 2022-02-24 12:03:40 +08:00 committed by GitHub
parent 484b75bb53
commit 02ca473492
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 16 additions and 126 deletions

View File

@ -6,7 +6,7 @@ from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from common.tree import TreeNodeSerializer from common.tree import TreeNodeSerializer
from common.mixins.views import SuggestionMixin from common.mixins.api import SuggestionMixin
from .. import serializers from .. import serializers
from ..models import Application from ..models import Application

View File

@ -1,18 +0,0 @@
# Generated by Django 3.1.14 on 2022-02-23 08:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0017_auto_20220217_2135'),
]
operations = [
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.1.14 on 2022-02-23 08:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0086_auto_20220217_2135'),
]
operations = [
migrations.AlterField(
model_name='systemuser',
name='protocol',
field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('k8s', 'K8S')], default='ssh', max_length=16, verbose_name='Protocol'),
),
]

View File

@ -8,7 +8,6 @@ from rest_framework.decorators import action
from rest_framework.request import Request from rest_framework.request import Request
from common.const.http import POST from common.const.http import POST
from common.permissions import IsValidUser
__all__ = ['SuggestionMixin', 'RenderToJsonMixin'] __all__ = ['SuggestionMixin', 'RenderToJsonMixin']
@ -23,8 +22,8 @@ class SuggestionMixin:
get_serializer: Callable get_serializer: Callable
get_paginated_response: Callable get_paginated_response: Callable
@action(methods=['get'], detail=False, permission_classes=(IsValidUser,)) @action(methods=['get'], detail=False, url_path='suggestions')
def suggestions(self, request, *args, **kwargs): def match(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) queryset = self.filter_queryset(self.get_queryset())
queryset = queryset[:self.suggestion_limit] queryset = queryset[:self.suggestion_limit]
page = self.paginate_queryset(queryset) page = self.paginate_queryset(queryset)

View File

@ -8,7 +8,7 @@ from rest_framework.response import Response
from common.permissions import IsValidUser from common.permissions import IsValidUser
__all__ = ["PermissionsMixin", "SuggestionMixin"] __all__ = ["PermissionsMixin"]
class PermissionsMixin(UserPassesTestMixin): class PermissionsMixin(UserPassesTestMixin):
@ -24,19 +24,3 @@ class PermissionsMixin(UserPassesTestMixin):
if not permission_class().has_permission(self.request, self): if not permission_class().has_permission(self.request, self):
return False return False
return True return True
class SuggestionMixin:
suggestion_mini_count = 10
@action(methods=['get'], detail=False, permission_classes=(IsValidUser,))
def suggestions(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
queryset = queryset[:self.suggestion_mini_count]
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

View File

@ -1,18 +0,0 @@
# Generated by Django 3.1.14 on 2022-02-23 08:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0024_auto_20220217_2135'),
]
operations = [
migrations.AlterField(
model_name='applicationpermission',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@ -7,6 +7,7 @@ auditor_perms = (
('common', 'permission', 'view', 'resourcestatistics'), ('common', 'permission', 'view', 'resourcestatistics'),
('audits', '*', '*', '*'), ('audits', '*', '*', '*'),
('rbac', 'menupermission', 'view', 'auditview'), ('rbac', 'menupermission', 'view', 'auditview'),
('terminal', 'commandstorage', 'view', 'commandstorage'),
('terminal', 'session', '*', '*'), ('terminal', 'session', '*', '*'),
('terminal', 'command', '*', '*'), ('terminal', 'command', '*', '*'),
) )

View File

@ -29,8 +29,8 @@ __all__ = ['CommandViewSet', 'CommandExportApi', 'InsecureCommandAlertAPI']
class CommandQueryMixin: class CommandQueryMixin:
command_store = get_command_storage() command_store = get_command_storage()
filterset_fields = [ filterset_fields = [
"asset", "system_user", "user", "session", "risk_level", "asset", "system_user", "user", "session",
"input" "risk_level", "input"
] ]
default_days_ago = 5 default_days_ago = 5

View File

@ -1,18 +0,0 @@
# Generated by Django 3.1.14 on 2022-02-23 08:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0043_auto_20220217_2135'),
]
operations = [
migrations.AlterField(
model_name='session',
name='protocol',
field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('sqlserver', 'sqlserver'), ('postgresql', 'postgresql'), ('redis', 'redis'), ('mongodb', 'MongoDB'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16),
),
]

View File

@ -9,6 +9,7 @@ from rest_framework_bulk import BulkModelViewSet
from common.mixins import CommonApiMixin from common.mixins import CommonApiMixin
from common.utils import get_logger from common.utils import get_logger
from common.mixins.api import SuggestionMixin
from orgs.utils import current_org from orgs.utils import current_org
from rbac.models import Role, RoleBinding from rbac.models import Role, RoleBinding
from users.utils import LoginBlockUtil, MFABlockUtils from users.utils import LoginBlockUtil, MFABlockUtils
@ -30,7 +31,7 @@ __all__ = [
] ]
class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet): class UserViewSet(CommonApiMixin, UserQuerysetMixin, SuggestionMixin, BulkModelViewSet):
filterset_class = UserFilter filterset_class = UserFilter
search_fields = ('username', 'email', 'name', 'id', 'source', 'role') search_fields = ('username', 'email', 'name', 'id', 'source', 'role')
serializer_classes = { serializer_classes = {
@ -41,7 +42,7 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet):
ordering_fields = ('name',) ordering_fields = ('name',)
ordering = ('name',) ordering = ('name',)
rbac_perms = { rbac_perms = {
'suggestion': 'users.match_user', 'match': 'users.match_user',
'invite': 'users.invite_user', 'invite': 'users.invite_user',
'remove': 'users.remove_user', 'remove': 'users.remove_user',
'bulk_remove': 'users.remove_user', 'bulk_remove': 'users.remove_user',
@ -51,18 +52,14 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet):
queryset = super().get_queryset().prefetch_related('groups') queryset = super().get_queryset().prefetch_related('groups')
return queryset return queryset
def list(self, request, *args, **kwargs): def paginate_queryset(self, queryset):
queryset = self.filter_queryset(self.get_queryset()) page = super().paginate_queryset(queryset)
page = self.paginate_queryset(queryset) if page:
if page is not None:
page = self.set_users_roles_for_cache(page) page = self.set_users_roles_for_cache(page)
serializer = self.get_serializer(page, many=True) else:
return self.get_paginated_response(serializer.data) self.set_users_roles_for_cache(queryset)
return page
queryset = self.set_users_roles_for_cache(queryset)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@staticmethod @staticmethod
def set_users_roles_for_cache(queryset): def set_users_roles_for_cache(queryset):
@ -87,7 +84,6 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet):
for u in queryset_list: for u in queryset_list:
system_roles = user_system_role_mapper[u.id] system_roles = user_system_role_mapper[u.id]
org_roles = user_org_role_mapper[u.id] org_roles = user_org_role_mapper[u.id]
u.roles.cache_set(system_roles | org_roles)
u.org_roles.cache_set(org_roles) u.org_roles.cache_set(org_roles)
u.system_roles.cache_set(system_roles) u.system_roles.cache_set(system_roles)
return queryset_list return queryset_list
@ -112,13 +108,6 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet):
self.check_object_permissions(self.request, obj) self.check_object_permissions(self.request, obj)
self.perform_destroy(obj) self.perform_destroy(obj)
@action(methods=['get'], detail=False)
def suggestion(self, *args, **kwargs):
queryset = User.get_nature_users()
queryset = self.filter_queryset(queryset)[:6]
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@action(methods=['post'], detail=False) @action(methods=['post'], detail=False)
def invite(self, request): def invite(self, request):
if not current_org or current_org.is_root(): if not current_org or current_org.is_root():

View File

@ -11,7 +11,6 @@ from rbac.models import OrgRoleBinding, SystemRoleBinding
from ..models import User from ..models import User
from ..const import PasswordStrategy from ..const import PasswordStrategy
from rbac.models import Role from rbac.models import Role
from rbac.builtin import BuiltinRole
__all__ = [ __all__ = [
'UserSerializer', 'MiniUserSerializer', 'UserSerializer', 'MiniUserSerializer',
@ -180,16 +179,6 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer
attrs = self.clean_auth_fields(attrs) attrs = self.clean_auth_fields(attrs)
attrs.pop('password_strategy', None) attrs.pop('password_strategy', None)
return attrs return attrs
# Todo: 不知道怎么优化呢
# def get_can_update(self, obj):
# return CanUpdateDeleteUser.has_update_object_permission(
# self.context['request'], self.context['view'], obj
# )
#
# def get_can_delete(self, obj):
# return CanUpdateDeleteUser.has_delete_object_permission(
# self.context['request'], self.context['view'], obj
# )
def save_and_set_custom_m2m_fields(self, validated_data, save_handler): def save_and_set_custom_m2m_fields(self, validated_data, save_handler):
m2m_values = { m2m_values = {