[Update] serializer mixin继承 (#2810)

* [Update] serializer mixin继承

* [Update] 修改system user更新serialzier

* [Update] 修改success message
pull/2817/head
老广 2019-06-19 16:45:14 +08:00 committed by GitHub
parent d6165e5975
commit 10616b8d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 102 additions and 51 deletions

View File

@ -4,8 +4,8 @@
from rest_framework import serializers from rest_framework import serializers
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from .. import const from .. import const
from ..models import RemoteApp from ..models import RemoteApp
@ -66,7 +66,7 @@ class RemoteAppParamsDictField(serializers.DictField):
return value return value
class RemoteAppSerializer(BulkSerializerMixin, serializers.ModelSerializer): class RemoteAppSerializer(BulkOrgResourceModelSerializer):
params = RemoteAppParamsDictField() params = RemoteAppParamsDictField()
class Meta: class Meta:

View File

@ -8,11 +8,12 @@ from common.serializers import AdaptedBulkListSerializer
from ..models import Node, AdminUser from ..models import Node, AdminUser
from ..const import ADMIN_USER_CONN_CACHE_KEY from ..const import ADMIN_USER_CONN_CACHE_KEY
from orgs.mixins import BulkOrgResourceModelSerializer
from .base import AuthSerializer from .base import AuthSerializer
class AdminUserSerializer(serializers.ModelSerializer): class AdminUserSerializer(BulkOrgResourceModelSerializer):
""" """
管理用户 管理用户
""" """
@ -27,7 +28,7 @@ class AdminUserSerializer(serializers.ModelSerializer):
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
model = AdminUser model = AdminUser
fields = [ fields = [
'id', 'org_id', 'name', 'username', 'assets_amount', 'id', 'name', 'username', 'assets_amount',
'reachable_amount', 'unreachable_amount', 'password', 'comment', 'reachable_amount', 'unreachable_amount', 'password', 'comment',
'date_created', 'date_updated', 'become', 'become_method', 'date_created', 'date_updated', 'become', 'become_method',
'become_user', 'created_by', 'become_user', 'created_by',

View File

@ -5,8 +5,7 @@ from rest_framework.validators import ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgResourceSerializerMixin from orgs.mixins import BulkOrgResourceModelSerializer
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from ..models import Asset, Protocol from ..models import Asset, Protocol
from .system_user import AssetSystemUserSerializer from .system_user import AssetSystemUserSerializer
@ -23,8 +22,7 @@ class ProtocolSerializer(serializers.ModelSerializer):
fields = ["name", "port"] fields = ["name", "port"]
class AssetSerializer(BulkSerializerMixin, OrgResourceSerializerMixin, class AssetSerializer(BulkOrgResourceModelSerializer):
serializers.ModelSerializer):
protocols = ProtocolSerializer(many=True) protocols = ProtocolSerializer(many=True)
""" """
@ -34,7 +32,7 @@ class AssetSerializer(BulkSerializerMixin, OrgResourceSerializerMixin,
model = Asset model = Asset
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
fields = [ fields = [
'id', 'org_id', 'org_name', 'ip', 'hostname', 'protocol', 'port', 'id', 'ip', 'hostname', 'protocol', 'port',
'protocols', 'platform', 'is_active', 'public_ip', 'domain', 'protocols', 'platform', 'is_active', 'public_ip', 'domain',
'admin_user', 'nodes', 'labels', 'number', 'vendor', 'model', 'sn', 'admin_user', 'nodes', 'labels', 'number', 'vendor', 'model', 'sn',
'cpu_model', 'cpu_count', 'cpu_cores', 'cpu_vcpus', 'memory', 'cpu_model', 'cpu_count', 'cpu_cores', 'cpu_vcpus', 'memory',
@ -93,7 +91,7 @@ class AssetSerializer(BulkSerializerMixin, OrgResourceSerializerMixin,
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
protocols_data = validated_data.pop("protocols") protocols_data = validated_data.pop("protocols", None)
# 兼容老的api # 兼容老的api
protocol = validated_data.get("protocol") protocol = validated_data.get("protocol")
@ -104,14 +102,16 @@ class AssetSerializer(BulkSerializerMixin, OrgResourceSerializerMixin,
if not protocol and not port and protocols_data: if not protocol and not port and protocols_data:
validated_data["protocol"] = protocols_data[0]["name"] validated_data["protocol"] = protocols_data[0]["name"]
validated_data["port"] = protocols_data[0]["port"] validated_data["port"] = protocols_data[0]["port"]
protocols = None
protocols_serializer = ProtocolSerializer(data=protocols_data, many=True) if protocols_data:
protocols_serializer.is_valid(raise_exception=True) protocols_serializer = ProtocolSerializer(data=protocols_data, many=True)
protocols = protocols_serializer.save() protocols_serializer.is_valid(raise_exception=True)
protocols = protocols_serializer.save()
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)
instance.protocols.all().delete() if protocols:
instance.protocols.set(protocols) instance.protocols.all().delete()
instance.protocols.set(protocols)
return instance return instance

View File

@ -9,6 +9,7 @@ from ..backends import AssetUserManager
from common.utils import validate_ssh_private_key from common.utils import validate_ssh_private_key
from common.mixins import BulkSerializerMixin from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
__all__ = [ __all__ = [
@ -23,7 +24,7 @@ class BasicAssetSerializer(serializers.ModelSerializer):
fields = ['hostname', 'ip'] fields = ['hostname', 'ip']
class AssetUserSerializer(BulkSerializerMixin, serializers.ModelSerializer): class AssetUserSerializer(BulkOrgResourceModelSerializer):
hostname = serializers.CharField(read_only=True, label=_("Hostname")) hostname = serializers.CharField(read_only=True, label=_("Hostname"))
ip = serializers.CharField(read_only=True, label=_("IP")) ip = serializers.CharField(read_only=True, label=_("IP"))
connectivity = serializers.CharField(read_only=True, label=_("Connectivity")) connectivity = serializers.CharField(read_only=True, label=_("Connectivity"))
@ -51,7 +52,7 @@ class AssetUserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
) )
fields = [ fields = [
"id", "hostname", "ip", "username", "password", "asset", "version", "id", "hostname", "ip", "username", "password", "asset", "version",
"is_latest", "connectivity", "backend", "org_id", "is_latest", "connectivity", "backend",
"date_created", "date_updated", "private_key", "public_key", "date_created", "date_updated", "private_key", "public_key",
] ]
extra_kwargs = { extra_kwargs = {

View File

@ -5,9 +5,10 @@ from rest_framework import serializers
from common.fields import ChoiceDisplayField from common.fields import ChoiceDisplayField
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from ..models import CommandFilter, CommandFilterRule, SystemUser from ..models import CommandFilter, CommandFilterRule, SystemUser
from orgs.mixins import BulkOrgResourceModelSerializer
class CommandFilterSerializer(serializers.ModelSerializer): class CommandFilterSerializer(BulkOrgResourceModelSerializer):
rules = serializers.PrimaryKeyRelatedField(queryset=CommandFilterRule.objects.all(), many=True) rules = serializers.PrimaryKeyRelatedField(queryset=CommandFilterRule.objects.all(), many=True)
system_users = serializers.PrimaryKeyRelatedField(queryset=SystemUser.objects.all(), many=True) system_users = serializers.PrimaryKeyRelatedField(queryset=SystemUser.objects.all(), many=True)
@ -17,7 +18,7 @@ class CommandFilterSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class CommandFilterRuleSerializer(serializers.ModelSerializer): class CommandFilterRuleSerializer(BulkOrgResourceModelSerializer):
serializer_choice_field = ChoiceDisplayField serializer_choice_field = ChoiceDisplayField
class Meta: class Meta:

View File

@ -3,11 +3,12 @@
from rest_framework import serializers from rest_framework import serializers
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import Domain, Gateway from ..models import Domain, Gateway
class DomainSerializer(serializers.ModelSerializer): class DomainSerializer(BulkOrgResourceModelSerializer):
asset_count = serializers.SerializerMethodField() asset_count = serializers.SerializerMethodField()
gateway_count = serializers.SerializerMethodField() gateway_count = serializers.SerializerMethodField()
@ -25,7 +26,7 @@ class DomainSerializer(serializers.ModelSerializer):
return obj.gateway_set.all().count() return obj.gateway_set.all().count()
class GatewaySerializer(serializers.ModelSerializer): class GatewaySerializer(BulkOrgResourceModelSerializer):
class Meta: class Meta:
model = Gateway model = Gateway
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
@ -45,7 +46,7 @@ class GatewayWithAuthSerializer(GatewaySerializer):
return fields return fields
class DomainWithGatewaySerializer(serializers.ModelSerializer): class DomainWithGatewaySerializer(BulkOrgResourceModelSerializer):
gateways = GatewayWithAuthSerializer(many=True, read_only=True) gateways = GatewayWithAuthSerializer(many=True, read_only=True)
class Meta: class Meta:

View File

@ -3,11 +3,12 @@
from rest_framework import serializers from rest_framework import serializers
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import Label from ..models import Label
class LabelSerializer(serializers.ModelSerializer): class LabelSerializer(BulkOrgResourceModelSerializer):
asset_count = serializers.SerializerMethodField() asset_count = serializers.SerializerMethodField()
class Meta: class Meta:
@ -25,7 +26,7 @@ class LabelSerializer(serializers.ModelSerializer):
return fields return fields
class LabelDistinctSerializer(serializers.ModelSerializer): class LabelDistinctSerializer(BulkOrgResourceModelSerializer):
value = serializers.SerializerMethodField() value = serializers.SerializerMethodField()
class Meta: class Meta:

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from rest_framework import serializers from rest_framework import serializers
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import Asset, Node from ..models import Asset, Node
@ -10,7 +11,7 @@ __all__ = [
] ]
class NodeSerializer(serializers.ModelSerializer): class NodeSerializer(BulkOrgResourceModelSerializer):
assets_amount = serializers.IntegerField(read_only=True) assets_amount = serializers.IntegerField(read_only=True)
class Meta: class Meta:

View File

@ -3,12 +3,12 @@ from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import SystemUser, Asset from ..models import SystemUser
from .base import AuthSerializer from .base import AuthSerializer
class SystemUserSerializer(serializers.ModelSerializer): class SystemUserSerializer(BulkOrgResourceModelSerializer):
""" """
系统用户 系统用户
""" """
@ -31,7 +31,7 @@ class SystemUserSerializer(serializers.ModelSerializer):
model = SystemUser model = SystemUser
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
fields = [ fields = [
'id', 'org_id', 'name', 'username', 'login_mode', 'id', 'name', 'username', 'login_mode', 'login_mode_display',
'login_mode_display', 'priority', 'protocol', 'auto_push', 'login_mode_display', 'priority', 'protocol', 'auto_push',
'password', 'assets_amount', 'reachable_amount', 'reachable_assets', 'password', 'assets_amount', 'reachable_amount', 'reachable_assets',
'unreachable_amount', 'unreachable_assets', 'cmd_filters', 'sudo', 'unreachable_amount', 'unreachable_assets', 'cmd_filters', 'sudo',
@ -39,17 +39,9 @@ class SystemUserSerializer(serializers.ModelSerializer):
] ]
extra_kwargs = { extra_kwargs = {
'login_mode_display': {'label': _('Login mode display')}, 'login_mode_display': {'label': _('Login mode display')},
'created_by': {'read_only': True}, 'nodes': {'read_only': True}, 'created_by': {'read_only': True},
'assets': {'read_only': True}
} }
def get_field_names(self, declared_fields, info):
fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info)
fields.extend([
'login_mode_display',
])
return fields
@staticmethod @staticmethod
def get_unreachable_assets(obj): def get_unreachable_assets(obj):
return obj.assets_unreachable return obj.assets_unreachable

View File

@ -65,6 +65,7 @@ def on_system_user_update(sender, instance=None, created=True, **kwargs):
@receiver(m2m_changed, sender=SystemUser.nodes.through) @receiver(m2m_changed, sender=SystemUser.nodes.through)
def on_system_user_nodes_change(sender, instance=None, **kwargs): def on_system_user_nodes_change(sender, instance=None, **kwargs):
if instance and kwargs["action"] == "post_add": if instance and kwargs["action"] == "post_add":
logger.info("System user `{}` nodes update signal received".format(instance))
assets = set() assets = set()
nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
for node in nodes: for node in nodes:

View File

@ -76,6 +76,7 @@ function initTable2() {
function onNodeSelected2(event, treeNode) { function onNodeSelected2(event, treeNode) {
var url = asset_table2.ajax.url(); var url = asset_table2.ajax.url();
url = setUrlParam(url, "node_id", treeNode.meta.node.id); url = setUrlParam(url, "node_id", treeNode.meta.node.id);
url = setUrlParam(url, "show_current_asset", "");
asset_table2.ajax.url(url); asset_table2.ajax.url(url);
asset_table2.ajax.reload(); asset_table2.ajax.reload();
} }

View File

@ -20,7 +20,6 @@ from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.core.cache import cache from django.core.cache import cache
from django.utils import timezone from django.utils import timezone
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect from django.shortcuts import redirect
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.forms.formsets import formset_factory from django.forms.formsets import formset_factory

View File

@ -147,7 +147,23 @@ class PrivateTokenAuthentication(authentication.TokenAuthentication):
class SessionAuthentication(authentication.SessionAuthentication): class SessionAuthentication(authentication.SessionAuthentication):
def enforce_csrf(self, request): def authenticate(self, request):
reason = CSRFCheck().process_view(request, None, (), {}) """
if reason: Returns a `User` if the request session currently has a logged in user.
raise exceptions.AuthenticationFailed(reason) Otherwise returns `None`.
"""
# Get the session-based user from the underlying HttpRequest object
user = getattr(request._request, 'user', None)
# Unauthenticated, CSRF validation not required
if not user or not user.is_active:
return None
try:
self.enforce_csrf(request)
except exceptions.AuthenticationFailed:
return None
# CSRF passed with authenticated user
return user, None

View File

@ -211,6 +211,8 @@ class ApiMessageMixin:
_action_map = {"create": _("create"), "update": _("update")} _action_map = {"create": _("create"), "update": _("update")}
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
if not isinstance(cleaned_data, dict):
return ''
data = {k: v for k, v in cleaned_data.items()} data = {k: v for k, v in cleaned_data.items()}
action = getattr(self, "action", "create") action = getattr(self, "action", "create")
data["action"] = self._action_map.get(action) data["action"] = self._action_map.get(action)

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .models import Organization
from .utils import get_org_from_request, set_current_org from .utils import get_org_from_request, set_current_org
@ -8,7 +9,21 @@ class OrgMiddleware:
def __init__(self, get_response): def __init__(self, get_response):
self.get_response = get_response self.get_response = get_response
@staticmethod
def set_permed_org_if_need(request):
if request.content_type != "text/plain":
return
if not (request.user.is_authenticated and request.user.is_org_admin):
return
org = get_org_from_request(request)
if org.can_admin_by(request.user):
return
admin_orgs = Organization.get_user_admin_orgs(request.user)
if admin_orgs:
request.session['oid'] = str(admin_orgs[0].id)
def __call__(self, request): def __call__(self, request):
self.set_permed_org_if_need(request)
org = get_org_from_request(request) org = get_org_from_request(request)
request.current_org = org request.current_org = org
set_current_org(org) set_current_org(org)

View File

@ -13,6 +13,7 @@ from rest_framework.validators import UniqueTogetherValidator
from common.utils import get_logger from common.utils import get_logger
from common.validators import ProjectUniqueValidator from common.validators import ProjectUniqueValidator
from common.mixins import BulkSerializerMixin
from .utils import ( from .utils import (
current_org, set_current_org, set_to_root_org, get_current_org_id current_org, set_current_org, set_to_root_org, get_current_org_id
) )
@ -25,6 +26,7 @@ __all__ = [
'OrgManager', 'OrgViewGenericMixin', 'OrgModelMixin', 'OrgModelForm', 'OrgManager', 'OrgViewGenericMixin', 'OrgModelMixin', 'OrgModelForm',
'RootOrgViewMixin', 'OrgMembershipSerializerMixin', 'RootOrgViewMixin', 'OrgMembershipSerializerMixin',
'OrgMembershipModelViewSetMixin', 'OrgResourceSerializerMixin', 'OrgMembershipModelViewSetMixin', 'OrgResourceSerializerMixin',
'BulkOrgResourceSerializerMixin', 'BulkOrgResourceModelSerializer',
] ]
@ -217,7 +219,7 @@ class OrgResourceSerializerMixin(serializers.Serializer):
由于HiddenField字段不可读API获取资产信息时获取不到org_id 由于HiddenField字段不可读API获取资产信息时获取不到org_id
但是coco需要资产的org_id字段所以修改为CharField类型 但是coco需要资产的org_id字段所以修改为CharField类型
""" """
org_id = serializers.CharField(default=get_current_org_id) org_id = serializers.ReadOnlyField(default=get_current_org_id)
def get_validators(self): def get_validators(self):
_validators = super().get_validators() _validators = super().get_validators()
@ -229,3 +231,16 @@ class OrgResourceSerializerMixin(serializers.Serializer):
v = ProjectUniqueValidator(v.queryset, v.fields) v = ProjectUniqueValidator(v.queryset, v.fields)
validators.append(v) validators.append(v)
return validators return validators
def get_field_names(self, declared_fields, info):
fields = super().get_field_names(declared_fields, info)
fields.extend(["org_id", "org_name"])
return fields
class BulkOrgResourceSerializerMixin(BulkSerializerMixin, OrgResourceSerializerMixin):
pass
class BulkOrgResourceModelSerializer(BulkOrgResourceSerializerMixin, serializers.ModelSerializer):
pass

View File

@ -4,6 +4,7 @@
from rest_framework import serializers from rest_framework import serializers
from common.fields import StringManyToManyField from common.fields import StringManyToManyField
from orgs.mixins import BulkOrgResourceModelSerializer
from perms.models import AssetPermission, Action from perms.models import AssetPermission, Action
from assets.models import Node from assets.models import Node
from assets.serializers import AssetGrantedSerializer from assets.serializers import AssetGrantedSerializer
@ -22,13 +23,13 @@ class ActionSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class AssetPermissionCreateUpdateSerializer(serializers.ModelSerializer): class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer):
class Meta: class Meta:
model = AssetPermission model = AssetPermission
exclude = ('created_by', 'date_created') exclude = ('created_by', 'date_created')
class AssetPermissionListSerializer(serializers.ModelSerializer): class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
users = StringManyToManyField(many=True, read_only=True) users = StringManyToManyField(many=True, read_only=True)
user_groups = StringManyToManyField(many=True, read_only=True) user_groups = StringManyToManyField(many=True, read_only=True)
assets = StringManyToManyField(many=True, read_only=True) assets = StringManyToManyField(many=True, read_only=True)

View File

@ -3,6 +3,8 @@
from rest_framework import serializers from rest_framework import serializers
from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import RemoteAppPermission from ..models import RemoteAppPermission
@ -13,13 +15,14 @@ __all__ = [
] ]
class RemoteAppPermissionSerializer(serializers.ModelSerializer): class RemoteAppPermissionSerializer(BulkOrgResourceModelSerializer):
class Meta: class Meta:
model = RemoteAppPermission model = RemoteAppPermission
list_serializer_class = AdaptedBulkListSerializer
fields = [ fields = [
'id', 'name', 'users', 'user_groups', 'remote_apps', 'comment', 'id', 'name', 'users', 'user_groups', 'remote_apps', 'comment',
'is_active', 'date_start', 'date_expired', 'is_valid', 'is_active', 'date_start', 'date_expired', 'is_valid',
'created_by', 'date_created', 'org_id' 'created_by', 'date_created',
] ]
read_only_fields = ['created_by', 'date_created'] read_only_fields = ['created_by', 'date_created']

View File

@ -2,7 +2,6 @@
# #
from django.views.generic import ListView, UpdateView, DeleteView, \ from django.views.generic import ListView, UpdateView, DeleteView, \
DetailView, View DetailView, View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse_lazy, reverse from django.urls import reverse_lazy, reverse

View File

@ -7,6 +7,7 @@ from rest_framework import serializers
from common.utils import get_signer, validate_ssh_public_key from common.utils import get_signer, validate_ssh_public_key
from common.mixins import BulkSerializerMixin from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import User, UserGroup from ..models import User, UserGroup
signer = get_signer() signer = get_signer()
@ -56,7 +57,7 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer):
fields = ['id', 'groups'] fields = ['id', 'groups']
class UserGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer): class UserGroupSerializer(BulkOrgResourceModelSerializer):
users = serializers.PrimaryKeyRelatedField( users = serializers.PrimaryKeyRelatedField(
required=False, many=True, queryset=User.objects.all(), label=_('User') required=False, many=True, queryset=User.objects.all(), label=_('User')
) )