diff --git a/apps/audits/handler.py b/apps/audits/handler.py index 7d9e331cb..3f0e444f1 100644 --- a/apps/audits/handler.py +++ b/apps/audits/handler.py @@ -12,7 +12,10 @@ from common.utils.timezone import as_current_tz from jumpserver.utils import current_request from orgs.models import Organization from orgs.utils import get_current_org_id +from settings.models import Setting from settings.serializers import SettingsSerializer +from users.models import Preference +from users.serializers import PreferenceSerializer from .backends import get_operate_log_storage logger = get_logger(__name__) @@ -87,19 +90,15 @@ class OperatorLogHandler(metaclass=Singleton): return log_id, before, after @staticmethod - def get_resource_display_from_setting(resource): - resource_display = None - setting_serializer = SettingsSerializer() - label = setting_serializer.get_field_label(resource) - if label is not None: - resource_display = label - return resource_display - - def get_resource_display(self, resource): - resource_display = str(resource) - return_value = self.get_resource_display_from_setting(resource_display) - if return_value is not None: - resource_display = return_value + def get_resource_display(resource): + if isinstance(resource, Setting): + serializer = SettingsSerializer() + resource_display = serializer.get_field_label(resource.name) + elif isinstance(resource, Preference): + serializer = PreferenceSerializer() + resource_display = serializer.get_field_label(resource.name) + else: + resource_display = str(resource) return resource_display @staticmethod diff --git a/apps/settings/serializers/settings.py b/apps/settings/serializers/settings.py index 743f7cc60..7349e3195 100644 --- a/apps/settings/serializers/settings.py +++ b/apps/settings/serializers/settings.py @@ -1,7 +1,7 @@ -# coding: utf-8 from django.core.cache import cache from django.utils import translation from django.utils.translation import gettext_noop, gettext_lazy as _ +from rest_framework import serializers from common.utils import i18n_fmt from .auth import ( @@ -20,11 +20,53 @@ from .security import SecuritySettingSerializer from .terminal import TerminalSettingSerializer __all__ = [ + 'BaseSerializerWithFieldLabel', 'SettingsSerializer', ] +class BaseSerializerWithFieldLabel: + CACHE_KEY: str + ignore_iter_fields = True + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.fields_label_mapping = None + + def extract_fields(self, serializer): + fields = {} + for field_name, field in serializer.get_fields().items(): + if isinstance(field, serializers.Serializer): + fields.update(self.extract_fields(field)) + else: + fields.update({field_name: field}) + return fields + + def get_field_label(self, field_name): + self.fields_label_mapping = cache.get(self.CACHE_KEY, None) + if self.fields_label_mapping is None: + self.fields_label_mapping = {} + with translation.override('en'): + cls = self.__class__ + base_name = getattr(cls, 'PREFIX_TITLE', cls.__name__) + + for subclass in cls.__bases__: + ignore_iter_fields = getattr(subclass, 'ignore_iter_fields', False) + if ignore_iter_fields: + continue + + prefix = getattr(subclass, 'PREFIX_TITLE', base_name) + fields = self.extract_fields(subclass()) + for name, item in fields.items(): + label = getattr(item, 'label', '') + detail = i18n_fmt(gettext_noop('[%s] %s'), prefix, label) + self.fields_label_mapping[name] = detail + cache.set(self.CACHE_KEY, self.fields_label_mapping, 3600 * 24) + return self.fields_label_mapping.get(field_name, field_name) + + class SettingsSerializer( + BaseSerializerWithFieldLabel, BasicSettingSerializer, LDAPSettingSerializer, AuthSettingSerializer, @@ -49,25 +91,5 @@ class SettingsSerializer( CustomSMSSettingSerializer, PasskeySettingSerializer ): + PREFIX_TITLE = _('Setting') CACHE_KEY = 'SETTING_FIELDS_MAPPING' - - # encrypt_fields 现在使用 write_only 来判断了 - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.fields_label_mapping = None - - # 单次计算量不大,搞个缓存,以防操作日志大量写入时,这里影响性能 - def get_field_label(self, field_name): - self.fields_label_mapping = cache.get(self.CACHE_KEY, None) - if self.fields_label_mapping is None: - self.fields_label_mapping = {} - with translation.override('en'): - for subclass in SettingsSerializer.__bases__: - prefix = getattr(subclass, 'PREFIX_TITLE', _('Setting')) - fields = subclass().get_fields() - for name, item in fields.items(): - label = getattr(item, 'label', '') - detail = i18n_fmt(gettext_noop('[%s] %s'), prefix, label) - self.fields_label_mapping[name] = detail - cache.set(self.CACHE_KEY, self.fields_label_mapping, 3600 * 24) - return self.fields_label_mapping.get(field_name) diff --git a/apps/users/serializers/preference/__init__.py b/apps/users/serializers/preference/__init__.py index 2ea5a6e9a..74f194dda 100644 --- a/apps/users/serializers/preference/__init__.py +++ b/apps/users/serializers/preference/__init__.py @@ -1,3 +1,4 @@ from .koko import * from .lina import * from .luna import * +from .preference import * diff --git a/apps/users/serializers/preference/preference.py b/apps/users/serializers/preference/preference.py new file mode 100644 index 000000000..1c68e2906 --- /dev/null +++ b/apps/users/serializers/preference/preference.py @@ -0,0 +1,20 @@ +from django.utils.translation import gettext_lazy as _ + +from settings.serializers import BaseSerializerWithFieldLabel +from .koko import KokoSerializer +from .lina import LinaSerializer +from .luna import LunaSerializer + +__all__ = [ + 'PreferenceSerializer', +] + + +class PreferenceSerializer( + BaseSerializerWithFieldLabel, + LinaSerializer, + LunaSerializer, + KokoSerializer +): + PREFIX_TITLE = _('Preference') + CACHE_KEY = 'PREFERENCE_FIELDS_MAPPING'