From 0c80e3e815636179b1b25096089d60c220239d89 Mon Sep 17 00:00:00 2001
From: ibuler <ibuler@qq.com>
Date: Thu, 29 Mar 2018 15:02:09 +0800
Subject: [PATCH] [rev] for api commit

---
 apps/assets/api/admin_user.py          |  9 ++++++++-
 apps/assets/api/system_user.py         |  9 ---------
 apps/assets/serializers/admin_user.py  | 17 ++++++++++++++++
 apps/assets/serializers/base.py        | 28 ++++++++++++++++++++++++++
 apps/assets/serializers/system_user.py |  5 ++---
 apps/assets/urls/api_urls.py           | 14 ++-----------
 apps/users/serializers.py              |  2 +-
 7 files changed, 58 insertions(+), 26 deletions(-)
 create mode 100644 apps/assets/serializers/base.py

diff --git a/apps/assets/api/admin_user.py b/apps/assets/api/admin_user.py
index a69d771b3..e32bbe02a 100644
--- a/apps/assets/api/admin_user.py
+++ b/apps/assets/api/admin_user.py
@@ -28,7 +28,8 @@ from ..tasks import test_admin_user_connectability_manual
 
 logger = get_logger(__file__)
 __all__ = [
-    'AdminUserViewSet', 'ReplaceNodesAdminUserApi', 'AdminUserTestConnectiveApi'
+    'AdminUserViewSet', 'ReplaceNodesAdminUserApi',
+    'AdminUserTestConnectiveApi', 'AdminUserAuthApi',
 ]
 
 
@@ -41,6 +42,12 @@ class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
     permission_classes = (IsSuperUser,)
 
 
+class AdminUserAuthApi(generics.UpdateAPIView):
+    queryset = AdminUser.objects.all()
+    serializer_class = serializers.AdminUserAuthSerializer
+    permission_classes = (IsSuperUser,)
+
+
 class ReplaceNodesAdminUserApi(generics.UpdateAPIView):
     queryset = AdminUser.objects.all()
     serializer_class = serializers.ReplaceNodeAdminUserSerializer
diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py
index dd92afad4..ca2a6b7f0 100644
--- a/apps/assets/api/system_user.py
+++ b/apps/assets/api/system_user.py
@@ -48,15 +48,6 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView):
     permission_classes = (IsSuperUserOrAppUser,)
     serializer_class = serializers.SystemUserAuthSerializer
 
-    def update(self, request, *args, **kwargs):
-        password = request.data.pop("password", None)
-        private_key = request.data.pop("private_key", None)
-        instance = self.get_object()
-
-        if password or private_key:
-            instance.set_auth(password=password, private_key=private_key)
-        return super().update(request, *args, **kwargs)
-
 
 class SystemUserPushApi(generics.RetrieveAPIView):
     """
diff --git a/apps/assets/serializers/admin_user.py b/apps/assets/serializers/admin_user.py
index d59ca64ae..dbd0d1b39 100644
--- a/apps/assets/serializers/admin_user.py
+++ b/apps/assets/serializers/admin_user.py
@@ -2,9 +2,12 @@
 #
 from django.core.cache import cache
 from rest_framework import serializers
+
 from ..models import Node, AdminUser
 from ..const import ADMIN_USER_CONN_CACHE_KEY
 
+from .base import AuthSerializer
+
 
 class AdminUserSerializer(serializers.ModelSerializer):
     """
@@ -18,6 +21,10 @@ class AdminUserSerializer(serializers.ModelSerializer):
         model = AdminUser
         fields = '__all__'
 
+    def get_field_names(self, declared_fields, info):
+        fields = super().get_field_names(declared_fields, info)
+        return [f for f in fields if not f.startswith('_')]
+
     @staticmethod
     def get_unreachable_amount(obj):
         data = cache.get(ADMIN_USER_CONN_CACHE_KEY.format(obj.name))
@@ -39,6 +46,13 @@ class AdminUserSerializer(serializers.ModelSerializer):
         return obj.assets_amount
 
 
+class AdminUserAuthSerializer(AuthSerializer):
+
+    class Meta:
+        model = AdminUser
+        fields = ['password', 'private_key']
+
+
 class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer):
     """
     管理用户更新关联到的集群
@@ -50,3 +64,6 @@ class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer):
     class Meta:
         model = AdminUser
         fields = ['id', 'nodes']
+
+
+
diff --git a/apps/assets/serializers/base.py b/apps/assets/serializers/base.py
new file mode 100644
index 000000000..2e8bbba07
--- /dev/null
+++ b/apps/assets/serializers/base.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+#
+
+from rest_framework import serializers
+from common.utils import ssh_pubkey_gen
+
+
+class AuthSerializer(serializers.ModelSerializer):
+    password = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=1024)
+    private_key = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=4096)
+
+    def gen_keys(self, private_key=None, password=None):
+        if private_key is None:
+            return None, None
+        public_key = ssh_pubkey_gen(private_key=private_key, password=password)
+        return private_key, public_key
+
+    def save(self, **kwargs):
+        password = self.validated_data.pop('password') or None
+        private_key = self.validated_data.pop('private_key') or None
+        self.instance = super().save(**kwargs)
+        if password or private_key:
+            private_key, public_key = self.gen_keys(private_key, password)
+            self.instance.set_auth(password=password, private_key=private_key,
+                                   public_key=public_key)
+        return self.instance
+
+
diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py
index 38aad66ce..1dff79422 100644
--- a/apps/assets/serializers/system_user.py
+++ b/apps/assets/serializers/system_user.py
@@ -1,6 +1,7 @@
 from rest_framework import serializers
 
 from ..models import SystemUser
+from .base import AuthSerializer
 
 
 class SystemUserSerializer(serializers.ModelSerializer):
@@ -36,12 +37,10 @@ class SystemUserSerializer(serializers.ModelSerializer):
         return len(obj.assets)
 
 
-class SystemUserAuthSerializer(serializers.ModelSerializer):
+class SystemUserAuthSerializer(AuthSerializer):
     """
     系统用户认证信息
     """
-    password = serializers.CharField(max_length=1024)
-    private_key = serializers.CharField(max_length=4096)
 
     class Meta:
         model = SystemUser
diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py
index bfcb1c70c..26bb4f96f 100644
--- a/apps/assets/urls/api_urls.py
+++ b/apps/assets/urls/api_urls.py
@@ -7,9 +7,7 @@ app_name = 'assets'
 
 
 router = BulkRouter()
-# router.register(r'v1/groups', api.AssetGroupViewSet, 'asset-group')
 router.register(r'v1/assets', api.AssetViewSet, 'asset')
-# router.register(r'v1/clusters', api.ClusterViewSet, 'cluster')
 router.register(r'v1/admin-user', api.AdminUserViewSet, 'admin-user')
 router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user')
 router.register(r'v1/labels', api.LabelViewSet, 'label')
@@ -25,18 +23,10 @@ urlpatterns = [
         api.AssetAdminUserTestApi.as_view(), name='asset-alive-test'),
     url(r'^v1/assets/user-assets/$',
         api.UserAssetListView.as_view(), name='user-asset-list'),
-    # update the asset group, which add or delete the asset to the group
-    #url(r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
-    #    api.GroupUpdateAssetsApi.as_view(), name='group-update-assets'),
-    #url(r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$',
-    #    api.GroupAddAssetsApi.as_view(), name='group-add-assets'),
-    # update the Cluster, and add or delete the assets to the Cluster
-    #url(r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
-    #    api.ClusterAddAssetsApi.as_view(), name='cluster-add-assets'),
-    #url(r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]{36})/assets/connective/$',
-    #    api.ClusterTestAssetsAliveApi.as_view(), name='cluster-test-connective'),
     url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
         api.ReplaceNodesAdminUserApi.as_view(), name='replace-nodes-admin-user'),
+    url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/auth/$',
+        api.AdminUserAuthApi.as_view(), name='admin-user-auth'),
     url(r'^v1/admin-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$',
         api.AdminUserTestConnectiveApi.as_view(), name='admin-user-connective'),
     url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/push/$',
diff --git a/apps/users/serializers.py b/apps/users/serializers.py
index e72f97407..9d14a1d3a 100644
--- a/apps/users/serializers.py
+++ b/apps/users/serializers.py
@@ -14,7 +14,7 @@ signer = get_signer()
 
 class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
     groups_display = serializers.SerializerMethodField()
-    groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
+    groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all(), required=False)
 
     class Meta:
         model = User