diff --git a/apps/assets/serializers/favorite_asset.py b/apps/assets/serializers/favorite_asset.py index 7c024bf1a..cc0647943 100644 --- a/apps/assets/serializers/favorite_asset.py +++ b/apps/assets/serializers/favorite_asset.py @@ -4,7 +4,7 @@ from rest_framework import serializers from orgs.utils import tmp_to_root_org -from common.mixins import BulkSerializerMixin +from common.drf.serializers import BulkSerializerMixin from ..models import FavoriteAsset diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 9895176fd..8b9d28005 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -2,9 +2,8 @@ # from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from django.db.models import F -from common.mixins import BulkSerializerMixin +from common.drf.serializers import BulkSerializerMixin from terminal.models import Session from ops.models import CommandExecution from . import models diff --git a/apps/common/drf/serializers/__init__.py b/apps/common/drf/serializers/__init__.py new file mode 100644 index 000000000..7ecadafc7 --- /dev/null +++ b/apps/common/drf/serializers/__init__.py @@ -0,0 +1,2 @@ +from .common import * +from .mixin import * diff --git a/apps/common/drf/serializers.py b/apps/common/drf/serializers/common.py similarity index 67% rename from apps/common/drf/serializers.py rename to apps/common/drf/serializers/common.py index 4f2080c95..836914a60 100644 --- a/apps/common/drf/serializers.py +++ b/apps/common/drf/serializers/common.py @@ -1,3 +1,4 @@ + from rest_framework import serializers from rest_framework.serializers import Serializer from rest_framework.serializers import ModelSerializer @@ -6,22 +7,17 @@ from django.utils.translation import gettext_lazy as _ from django.utils.functional import cached_property from drf_writable_nested.serializers import WritableNestedModelSerializer -from common.mixins import BulkListSerializerMixin -from common.mixins.serializers import BulkSerializerMixin -from common.drf.fields import EncryptedField +from .mixin import BulkListSerializerMixin, BulkSerializerMixin + __all__ = [ 'MethodSerializer', 'EmptySerializer', 'BulkModelSerializer', 'AdaptedBulkListSerializer', 'CeleryTaskSerializer', - 'SecretReadableMixin', 'JMSWritableNestedModelSerializer', + 'JMSWritableNestedModelSerializer', 'GroupedChoiceSerializer', ] -# MethodSerializer -# ---------------- - - class MethodSerializer(serializers.Serializer): def __init__(self, method_name=None, **kwargs): self.method_name = method_name @@ -65,10 +61,6 @@ class MethodSerializer(serializers.Serializer): return self.serializer.get_initial() -# Other Serializer -# ---------------- - - class EmptySerializer(Serializer): pass @@ -94,30 +86,5 @@ class GroupedChoiceSerializer(ChoiceSerializer): children = ChoiceSerializer(many=True, label=_("Children")) -class SecretReadableMixin(serializers.Serializer): - """ 加密字段 (EncryptedField) 可读性 """ - - def __init__(self, *args, **kwargs): - super(SecretReadableMixin, self).__init__(*args, **kwargs) - if not hasattr(self, 'Meta') or not hasattr(self.Meta, 'extra_kwargs'): - return - extra_kwargs = self.Meta.extra_kwargs - for field_name, serializer_field in self.fields.items(): - if not isinstance(serializer_field, EncryptedField): - continue - if field_name not in extra_kwargs: - continue - field_extra_kwargs = extra_kwargs[field_name] - if 'write_only' not in field_extra_kwargs: - continue - serializer_field.write_only = field_extra_kwargs['write_only'] - - class JMSWritableNestedModelSerializer(WritableNestedModelSerializer): pass - # - # def _get_related_pk(self, data, model_class): - # pk = data.get('pk') or data.get('id') or data.get(model_class._meta.pk.attname) - # if pk: - # return str(pk) - # return None diff --git a/apps/common/mixins/serializers.py b/apps/common/drf/serializers/mixin.py similarity index 87% rename from apps/common/mixins/serializers.py rename to apps/common/drf/serializers/mixin.py index 93c0a2050..b0cbee27e 100644 --- a/apps/common/mixins/serializers.py +++ b/apps/common/drf/serializers/mixin.py @@ -1,21 +1,43 @@ -# -*- coding: utf-8 -*- -# from collections import Iterable from django.db.models import NOT_PROVIDED from django.core.exceptions import ObjectDoesNotExist from rest_framework.utils import html +from rest_framework import serializers from rest_framework.settings import api_settings from rest_framework.exceptions import ValidationError from rest_framework.fields import SkipField, empty +from common.drf.fields import EncryptedField +from common.utils import lazyproperty + __all__ = [ 'BulkSerializerMixin', 'BulkListSerializerMixin', - 'CommonSerializerMixin', 'CommonBulkSerializerMixin' + 'CommonSerializerMixin', 'CommonBulkSerializerMixin', + 'SecretReadableMixin', ] +class SecretReadableMixin(serializers.Serializer): + """ 加密字段 (EncryptedField) 可读性 """ + + def __init__(self, *args, **kwargs): + super(SecretReadableMixin, self).__init__(*args, **kwargs) + if not hasattr(self, 'Meta') or not hasattr(self.Meta, 'extra_kwargs'): + return + extra_kwargs = self.Meta.extra_kwargs + for field_name, serializer_field in self.fields.items(): + if not isinstance(serializer_field, EncryptedField): + continue + if field_name not in extra_kwargs: + continue + field_extra_kwargs = extra_kwargs[field_name] + if 'write_only' not in field_extra_kwargs: + continue + serializer_field.write_only = field_extra_kwargs['write_only'] + + class BulkSerializerMixin(object): """ Become rest_framework_bulk not support uuid as a primary key @@ -56,15 +78,15 @@ class BulkSerializerMixin(object): @classmethod def many_init(cls, *args, **kwargs): + from .common import AdaptedBulkListSerializer meta = getattr(cls, 'Meta', None) assert meta is not None, 'Must have `Meta`' if not hasattr(meta, 'list_serializer_class'): - from common.drf.serializers import AdaptedBulkListSerializer meta.list_serializer_class = AdaptedBulkListSerializer return super(BulkSerializerMixin, cls).many_init(*args, **kwargs) -class BulkListSerializerMixin(object): +class BulkListSerializerMixin: """ Become rest_framework_bulk doing bulk update raise Exception: 'QuerySet' object has no attribute 'pk' when doing bulk update @@ -289,9 +311,12 @@ class DynamicFieldsMixin: class CommonSerializerMixin(DynamicFieldsMixin, DefaultValueFieldsMixin): instance: None initial_data: dict - common_fields = [ + common_fields = ( 'comment', 'created_by', 'date_created', 'date_updated', - ] + ) + secret_fields = ( + 'password', 'token', 'secret', 'key', 'private_key', 'public_key', + ) def get_initial_value(self, attr, default=None): value = self.initial_data.get(attr) @@ -302,6 +327,14 @@ class CommonSerializerMixin(DynamicFieldsMixin, DefaultValueFieldsMixin): return value return default + def get_fields(self): + fields = super().get_fields() + for name, field in fields.items(): + if name in self.secret_fields and \ + not isinstance(self, SecretReadableMixin): + field.write_only = True + return fields + def get_field_names(self, declared_fields, info): names = super().get_field_names(declared_fields, info) common_names = [i for i in self.common_fields if i in names] diff --git a/apps/common/mixins/__init__.py b/apps/common/mixins/__init__.py index 4249b3d64..b2a7ec7e4 100644 --- a/apps/common/mixins/__init__.py +++ b/apps/common/mixins/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # from .models import * -from .serializers import * from .api import * from .views import * diff --git a/apps/orgs/mixins/serializers.py b/apps/orgs/mixins/serializers.py index 5c1a561e3..4ec936c2f 100644 --- a/apps/orgs/mixins/serializers.py +++ b/apps/orgs/mixins/serializers.py @@ -5,7 +5,7 @@ from rest_framework import serializers from rest_framework.validators import UniqueTogetherValidator from common.validators import ProjectUniqueValidator -from common.mixins import BulkSerializerMixin, CommonSerializerMixin +from common.drf.serializers import BulkSerializerMixin, CommonSerializerMixin from ..utils import get_current_org_id_for_serializer diff --git a/apps/perms/serializers/permission_relation.py b/apps/perms/serializers/permission_relation.py index 2384c4845..4c76ae3fa 100644 --- a/apps/perms/serializers/permission_relation.py +++ b/apps/perms/serializers/permission_relation.py @@ -2,7 +2,7 @@ # from rest_framework import serializers -from common.mixins import BulkSerializerMixin +from common.drf.serializers import BulkSerializerMixin from assets.models import Asset, Node from perms.models import AssetPermission from users.models import User diff --git a/apps/terminal/serializers/terminal.py b/apps/terminal/serializers/terminal.py index dd6565348..1ef4f6158 100644 --- a/apps/terminal/serializers/terminal.py +++ b/apps/terminal/serializers/terminal.py @@ -1,7 +1,7 @@ from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ -from common.drf.serializers import BulkModelSerializer, AdaptedBulkListSerializer +from common.drf.serializers import BulkModelSerializer from common.utils import is_uuid from users.serializers import ServiceAccountSerializer from common.utils import get_request_ip, pretty_string diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index eb03a0e6f..833752727 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -4,7 +4,7 @@ from functools import partial from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from common.mixins import CommonBulkSerializerMixin +from common.drf.serializers import CommonBulkSerializerMixin from common.validators import PhoneValidator from common.utils import pretty_string, get_logger from common.drf.fields import EncryptedField