diff --git a/apps/__init__.py b/apps/__init__.py
index 6110e1346664e7d5b434744d71763880787d1973..7f7347e2eeec82d7d00e2cb67b3439650ca2b8a9 100644
--- a/apps/__init__.py
+++ b/apps/__init__.py
@@ -2,4 +2,4 @@
 # -*- coding: utf-8 -*-
 # 
 
-__version__ = "1.0.0"
+__version__ = "1.2.0"
diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py
index d7499760a909cb1c28b4707697d63d4c2180f2ed..f123e4649af5e05080209a5ad8a7814fbe4d5744 100644
--- a/apps/assets/api/node.py
+++ b/apps/assets/api/node.py
@@ -32,6 +32,7 @@ __all__ = [
     'NodeViewSet', 'NodeChildrenApi',
     'NodeAssetsApi', 'NodeWithAssetsApi',
     'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
+    'NodeReplaceAssetsApi',
     'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
     'TestNodeConnectiveApi'
 ]
@@ -191,6 +192,19 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
             instance.assets.remove(*tuple(assets))
 
 
+class NodeReplaceAssetsApi(generics.UpdateAPIView):
+    serializer_class = serializers.NodeAssetsSerializer
+    queryset = Node.objects.all()
+    permission_classes = (IsSuperUser,)
+    instance = None
+
+    def perform_update(self, serializer):
+        assets = serializer.validated_data.get('assets')
+        instance = self.get_object()
+        for asset in assets:
+            asset.nodes.set([instance])
+
+
 class RefreshNodeHardwareInfoApi(APIView):
     permission_classes = (IsSuperUser,)
     model = Node
diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py
index 1f42a297878ec6a9e286983ae829cf96e920416b..5b3009305faf411ca8613f45178053b829eabc04 100644
--- a/apps/assets/models/asset.py
+++ b/apps/assets/models/asset.py
@@ -49,6 +49,7 @@ class Asset(models.Model):
     ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
     hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
     port = models.IntegerField(default=22, verbose_name=_('Port'))
+    platform = models.CharField(max_length=128, choices=PLATFORM_CHOICES, default='Linux', verbose_name=_('Platform'))
     domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"), on_delete=models.SET_NULL)
     nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes"))
     is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
@@ -72,7 +73,6 @@ class Asset(models.Model):
     disk_total = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk total'))
     disk_info = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk info'))
 
-    platform = models.CharField(max_length=128, choices=PLATFORM_CHOICES, default='Linux', verbose_name=_('Platform'))
     os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS'))
     os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS version'))
     os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
@@ -84,7 +84,7 @@ class Asset(models.Model):
     comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
 
     def __str__(self):
-        return self.hostname
+        return '{0.hostname}({0.ip})'.format(self)
 
     @property
     def is_valid(self):
diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py
index 99236f781a2ce6ca6b84dba9e76b60bbdfe964fc..ad806342be49c7fcc96b8ca994b8c61b10709206 100644
--- a/apps/assets/models/node.py
+++ b/apps/assets/models/node.py
@@ -19,7 +19,7 @@ class Node(models.Model):
     is_asset = False
 
     def __str__(self):
-        return self.value
+        return self.full_value
 
     @property
     def name(self):
@@ -30,7 +30,7 @@ class Node(models.Model):
         if self == self.__class__.root():
             return self.value
         else:
-            return '{}/{}'.format(self.value, self.parent.full_value)
+            return '{} / {}'.format(self.parent.full_value, self.value)
 
     @property
     def level(self):
@@ -72,7 +72,7 @@ class Node(models.Model):
             assets = Asset.objects.all()
         else:
             nodes = self.get_family()
-            assets = Asset.objects.filter(nodes__in=nodes)
+            assets = Asset.objects.filter(nodes__in=nodes).distinct()
         return assets
 
     def has_assets(self):
diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py
index e0de2cf49825bb162175d84e925a0480b29d9ae1..bf31b8491c5a14bf7841584700c71a37117025eb 100644
--- a/apps/assets/models/user.py
+++ b/apps/assets/models/user.py
@@ -109,7 +109,7 @@ class SystemUser(AssetUser):
     shell = models.CharField(max_length=64,  default='/bin/bash', verbose_name=_('Shell'))
 
     def __str__(self):
-        return self.name
+        return '{0.name}({0.username})'.format(self)
 
     def to_json(self):
         return {
diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py
index 381e1a4cff8bdd769172af55eb6176df0e9742c7..dd660bc4296b0f6bb50c6455a0827068219ee2e0 100644
--- a/apps/assets/tasks.py
+++ b/apps/assets/tasks.py
@@ -96,6 +96,9 @@ def update_assets_hardware_info_util(assets, task_name=None):
         task_name = _("更新资产硬件信息")
     tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
     hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
+    if not hostname_list:
+        logger.info("Not hosts get, may be asset is not active or not unixlike platform")
+        return {}
     task, created = update_or_create_ansible_task(
         task_name, hosts=hostname_list, tasks=tasks, pattern='all',
         options=const.TASK_OPTIONS, run_as_admin=True, created_by='System',
diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html
index b68ab0378aec235c3c73ae740372a12c754d90eb..c5cd48857ba4f98ec1c1d4fd864cfc047e677157 100644
--- a/apps/assets/templates/assets/_asset_list_modal.html
+++ b/apps/assets/templates/assets/_asset_list_modal.html
@@ -1,132 +1,125 @@
 {% extends '_modal.html' %}
 {% load i18n %}
+{% load static %}
 
 {% block modal_class %}modal-lg{% endblock %}
 {% block modal_id %}asset_list_modal{% endblock %}
-{#{% block modal_title%}{% trans "Please select assets" %}{% endblock %}#}
+{% block modal_title%}{% trans "Asset list" %}{% endblock %}
 {% block modal_body %}
-{#<div class="btn-group" style="float: right">#}
-{#   <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>#}
-{#   <ul class="dropdown-menu labels">#}
-{#       {% for label in labels %}#}
-{#           <li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>#}
-{#       {% endfor %}#}
-{#   </ul>#}
-{#</div>#}
-<table class="table table-striped table-bordered table-hover " id="asset_modal_table" width="100%">
-   <thead>
-       <tr>
-           <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
-           <th class="text-center">{% trans 'Hostname' %}</th>
-           <th class="text-center">{% trans 'IP' %}</th>
-           <th class="text-center">{% trans 'Hardware' %}</th>
-           <th class="text-center">{% trans 'Active' %}</th>
-           <th class="text-center">{% trans 'Reachable' %}</th>
-           <th class="text-center">{% trans 'Action' %}</th>
-       </tr>
-   </thead>
-   <tbody>
-   </tbody>
-</table>
-<div id="actions" class="hide">
-   <div class="input-group">
-       <select class="form-control m-b" style="width: auto" id="slct_bulk_update">
-           <option value="delete">{% trans 'Delete selected' %}</option>
-           <option value="update">{% trans 'Update selected' %}</option>
-           <option value="deactive">{% trans 'Deactive selected' %}</option>
-           <option value="active">{% trans 'Active selected' %}</option>
-       </select>
-       <div class="input-group-btn pull-left" style="padding-left: 5px;">
-           <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary">
-            {% trans 'Submit' %}
-           </button>
+<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
+<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
+<script src="{% static 'js/jquery.form.min.js' %}"></script>
+<style>
+.inmodal .modal-header {
+    padding: 10px 10px;
+    text-align: center;
+}
+
+#assetTree2.ztree * {
+    background-color: #f8fafb;
+}
+#assetTree2.ztree {
+    background-color: #f8fafb;
+}
+</style>
+
+<div class="wrapper wrapper-content">
+   <div class="row">
+       <div class="col-lg-3" id="split-left" style="padding-left: 3px">
+           <div class="ibox float-e-margins">
+               <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
+                   <div class="file-manager ">
+                       <div id="assetTree2" class="ztree">
+                       </div>
+                       <div class="clearfix"></div>
+                   </div>
+               </div>
+           </div>
+       </div>
+       <div class="col-lg-9 animated fadeInRight" id="split-right">
+           <div class="mail-box-header">
+               <table class="table table-striped table-bordered table-hover " id="asset_list_modal_table" style="width: 100%">
+                   <thead>
+                       <tr>
+                           <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
+                           <th class="text-center">{% trans 'Hostname' %}</th>
+                           <th class="text-center">{% trans 'IP' %}</th>
+                       </tr>
+                   </thead>
+                   <tbody>
+                   </tbody>
+               </table>
+           </div>
        </div>
    </div>
 </div>
-<script>
-
-var modal_table;
 
-function initModalTable() {
+<script>
+var zTree2, asset_table2 = 0;
+function initTable2() {
     var options = {
-        ele: $('#asset_modal_table'),
-        columnDefs: [
-            {targets: 1, createdCell: function (td, cellData, rowData) {
-                {% url 'assets:asset-detail' pk=DEFAULT_PK as the_url  %}
-                var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>';
-                $(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
-            }},
-            {targets: 3, createdCell: function (td, cellData, rowData) {
-                $(td).html(rowData.hardware_info)
-            }},
-            {targets: 4, createdCell: function (td, cellData) {
-                if (!cellData) {
-                    $(td).html('<i class="fa fa-times text-danger"></i>')
-                } else {
-                    $(td).html('<i class="fa fa-check text-navy"></i>')
-                }
-            }},
-            {targets: 5, createdCell: function (td, cellData) {
-                if (cellData === 'Unknown'){
-                    $(td).html('<i class="fa fa-circle text-warning"></i>')
-                } else if (!cellData) {
-                    $(td).html('<i class="fa fa-circle text-danger"></i>')
-                } else {
-                    $(td).html('<i class="fa fa-circle text-navy"></i>')
-                }
-            }},
-            {targets: 6, createdCell: function (td, cellData, rowData) {
-                var update_btn = '<a href="{% url "assets:asset-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
-                var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
-                $(td).html(update_btn + del_btn)
-            }}
-        ],
+        ele: $('#asset_list_modal_table'),
         ajax_url: '{% url "api-assets:asset-list" %}',
         columns: [
-            {data: "id"}, {data: "hostname" }, {data: "ip" },
-            {data: "cpu_cores"}, {data: "is_active", orderable: false },
-            {data: "is_connective", orderable: false}, {data: "id", orderable: false }
+            {data: "id"}, {data: "hostname" }, {data: "ip" }
         ],
-        op_html: $('#actions').html()
+        pageLength: 10
     };
-    modal_table = jumpserver.initServerSideDataTable(options);
-    return modal_table;
+    asset_table2 = jumpserver.initServerSideDataTable(options);
+    return asset_table2
 }
 
-$(document).ready(function(){
-   initModalTable();
-}).on('click', '#btn_select_assets', function () {
-    var data_table = $('#asset_modal_table').DataTable();
-    var id_list = [];
-    data_table.rows({selected: true}).every(function(){
-        id_list.push(this.data().id);
-    });
-    var current_node;
-    var nodes = zTree.getSelectedNodes();
-    if (nodes && nodes.length === 1) {
-        current_node = nodes[0]
-    } else {
-        return
-    }
+function onSelected2(event, treeNode) {
+    var url = asset_table2.ajax.url();
+    url = setUrlParam(url, "node_id", treeNode.id);
+    setCookie('node_selected', treeNode.id);
+    asset_table2.ajax.url(url);
+    asset_table2.ajax.reload();
+}
 
-    var data = {
-        'assets': id_list
-    };
 
-    var success = function () {
-        modal_table.ajax.reload()
+function initTree2() {
+    var setting = {
+        view: {
+            dblClickExpand: false,
+            showLine: true
+        },
+        data: {
+            simpleData: {
+                enable: true
+            }
+        },
+        callback: {
+            onSelected: onSelected2
+        }
     };
 
-    APIUpdateAttr({
-        'url': '/api/assets/v1/nodes/' + current_node.id + '/assets/add/',
-        'method': 'PUT',
-        'body': JSON.stringify(data),
-        'success': success
-    })
+    var zNodes = [];
+    $.get("{% url 'api-assets:node-list' %}", function(data, status){
+        $.each(data, function (index, value) {
+            value["pId"] = value["parent"];
+            value["open"] = true;
+            value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
+            value['value'] = value['value'];
+        });
+        zNodes = data;
+        $.fn.zTree.init($("#assetTree2"), setting, zNodes);
+        zTree2 = $.fn.zTree.getZTreeObj("assetTree2");
+    });
+}
+
+
+$(document).ready(function(){
+    initTable2();
+    initTree2();
 })
 </script>
+{% endblock %}
 
+{% block modal_button %}
+    {{ block.super }}
 {% endblock %}
-{% block modal_confirm_id %}btn_select_assets{% endblock %}
+{% block modal_confirm_id %}btn_asset_modal_confirm{% endblock %}
+
 
 
diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html
index fd57d96437eff04351bf59dafe31dd1a34701943..0b1b2865a4b624d28521a3c663153e09294f7844 100644
--- a/apps/assets/templates/assets/asset_detail.html
+++ b/apps/assets/templates/assets/asset_detail.html
@@ -305,9 +305,9 @@ $(document).ready(function () {
         success_message: success
     });
     if (status === "False") {
-            $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('True');
+        $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('True');
     }else{
-            $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('False');
+        $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('False');
     }
 }).on('click', '#btn-update-nodes', function () {
     if (Object.keys(jumpserver.nodes_selected).length === 0) {
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html
index 18dc31645e85dc5cb24c256ec8a8ca775048a1ea..04ba11e573b036fb449c7951d70f7789dc4b046a 100644
--- a/apps/assets/templates/assets/asset_list.html
+++ b/apps/assets/templates/assets/asset_list.html
@@ -59,57 +59,57 @@
                    <i class="fa fa-angle-left fa-x" id="toggle-icon"></i>
                </div>
            </div>
-               <div class="mail-box-header">
-                   <div class="uc pull-left m-r-5"><a class="btn btn-sm btn-primary btn-create-asset"> {% trans "Create asset" %} </a></div>
-                    <div class="html5buttons">
-                        <div class="dt-buttons btn-group">
-                            <a class="btn btn-default btn_import" data-toggle="modal" data-target="#asset_import_modal" tabindex="0">
-                                <span>{% trans "Import" %}</span>
-                            </a>
-                            <a class="btn btn-default btn_export" tabindex="0">
-                                <span>{% trans "Export" %}</span>
-                            </a>
-                        </div>
-                    </div>
-                   <div class="btn-group" style="float: right">
-                       <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
-                       <ul class="dropdown-menu labels">
-                           {% for label in labels %}
-                               <li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>
-                           {% endfor %}
-                       </ul>
+           <div class="mail-box-header">
+               <div class="uc pull-left m-r-5"><a class="btn btn-sm btn-primary btn-create-asset"> {% trans "Create asset" %} </a></div>
+               <div class="html5buttons">
+                   <div class="dt-buttons btn-group">
+                       <a class="btn btn-default btn_import" data-toggle="modal" data-target="#asset_import_modal" tabindex="0">
+                           <span>{% trans "Import" %}</span>
+                       </a>
+                       <a class="btn btn-default btn_export" tabindex="0">
+                           <span>{% trans "Export" %}</span>
+                       </a>
                    </div>
-                   <table class="table table-striped table-bordered table-hover " id="asset_list_table" style="width: 100%">
-                       <thead>
-                           <tr>
-                               <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
-                               <th class="text-center">{% trans 'Hostname' %}</th>
-                               <th class="text-center">{% trans 'IP' %}</th>
-                               <th class="text-center">{% trans 'Hardware' %}</th>
-                               <th class="text-center">{% trans 'Active' %}</th>
-                               <th class="text-center">{% trans 'Reachable' %}</th>
-                               <th class="text-center">{% trans 'Action' %}</th>
-                           </tr>
-                       </thead>
-                       <tbody>
-                       </tbody>
-                   </table>
-                   <div id="actions" class="hide">
-                       <div class="input-group">
-                           <select class="form-control m-b" style="width: auto" id="slct_bulk_update">
-                               <option value="delete">{% trans 'Delete selected' %}</option>
-                               <option value="update">{% trans 'Update selected' %}</option>
-                               <option value="remove">{% trans 'Remove from this node' %}</option>
-                               <option value="deactive">{% trans 'Deactive selected' %}</option>
-                               <option value="active">{% trans 'Active selected' %}</option>
-                           </select>
-                           <div class="input-group-btn pull-left" style="padding-left: 5px;">
-                               <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary">
-                                {% trans 'Submit' %}
-                               </button>
-                           </div>
+               </div>
+               <div class="btn-group" style="float: right">
+                  <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
+                  <ul class="dropdown-menu labels">
+                      {% for label in labels %}
+                          <li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>
+                      {% endfor %}
+                  </ul>
+               </div>
+               <table class="table table-striped table-bordered table-hover " id="asset_list_table" style="width: 100%">
+                   <thead>
+                       <tr>
+                           <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
+                           <th class="text-center">{% trans 'Hostname' %}</th>
+                           <th class="text-center">{% trans 'IP' %}</th>
+                           <th class="text-center">{% trans 'Hardware' %}</th>
+                           <th class="text-center">{% trans 'Active' %}</th>
+                           <th class="text-center">{% trans 'Reachable' %}</th>
+                           <th class="text-center">{% trans 'Action' %}</th>
+                       </tr>
+                   </thead>
+                   <tbody>
+                   </tbody>
+               </table>
+               <div id="actions" class="hide">
+                   <div class="input-group">
+                       <select class="form-control m-b" style="width: auto" id="slct_bulk_update">
+                           <option value="delete">{% trans 'Delete selected' %}</option>
+                           <option value="update">{% trans 'Update selected' %}</option>
+                           <option value="remove">{% trans 'Remove from this node' %}</option>
+                           <option value="deactive">{% trans 'Deactive selected' %}</option>
+                           <option value="active">{% trans 'Active selected' %}</option>
+                       </select>
+                       <div class="input-group-btn pull-left" style="padding-left: 5px;">
+                           <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary">
+                            {% trans 'Submit' %}
+                           </button>
                        </div>
                    </div>
+               </div>
            </div>
        </div>
    </div>
@@ -117,15 +117,16 @@
 
 <div id="rMenu">
     <ul class="dropdown-menu">
-        <li id="menu_asset_create" class="btn-create-asset" tabindex="-1"><a>{% trans 'Create asset' %}</a></li>
-        <li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a>{% trans 'Add asset' %}</a></li>
-        <li id="menu_refresh_hardware_info" class="btn-refresh-hardware" tabindex="-1"><a>{% trans 'Refresh node hardware info' %}</a></li>
-        <li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a>{% trans 'Test node connective' %}</a></li>
         <li class="divider"></li>
-        <li id="m_create" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Add node' %}</a></li>
-        <li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>{% trans 'Rename node' %}</a></li>
+        <li id="m_create" tabindex="-1" onclick="addTreeNode();"><a><i class="fa fa-plus-square-o"></i> {% trans 'Add node' %}</a></li>
+        <li id="m_del" tabindex="-1" onclick="editTreeNode();"><a><i class="fa fa-pencil-square-o"></i> {% trans 'Rename node' %}</a></li>
+        <li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a><i class="fa fa-minus-square"></i> {% trans 'Delete node' %}</a></li>
         <li class="divider"></li>
-        <li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>{% trans 'Delete node' %}</a></li>
+        <li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a><i class="fa fa-copy"></i> {% trans 'Add assets to node' %}</a></li>
+        <li id="menu_asset_move" class="btn-move-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a><i class="fa fa-cut"></i> {% trans 'Move assets to node' %}</a></li>
+        <li class="divider"></li>
+        <li id="menu_refresh_hardware_info" class="btn-refresh-hardware" tabindex="-1"><a><i class="fa fa-refresh"></i> {% trans 'Refresh node hardware info' %}</a></li>
+        <li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a><i class="fa fa-chain"></i> {% trans 'Test node connective' %}</a></li>
     </ul>
 </div>
 
@@ -136,6 +137,7 @@
 {% block custom_foot_js %}
 <script>
 var zTree, rMenu, asset_table, show = 0;
+var update_node_action = "";
 function initTable() {
     var options = {
         ele: $('#asset_list_table'),
@@ -210,10 +212,11 @@ function removeTreeNode() {
 	if (!current_node){
 	    return
     }
-
 	if (current_node.children && current_node.children.length > 0) {
-		alert("{% trans 'Have child node, cancel' %}")
-	} else {
+		toastr.error("{% trans 'Have child node, cancel' %}");
+	 } else if (current_node.assets_amount !== 0) {
+        toastr.error("{% trans 'Have assets, cancel' %}");
+    } else {
         var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id );
 		$.ajax({
             url: url,
@@ -249,13 +252,6 @@ function OnRightClick(event, treeId, treeNode) {
 
 function showRMenu(type, x, y) {
 	$("#rMenu ul").show();
-	{#if (type === "root") {#}
-	{#	return#}
-	{# } else {#}
-	{#	$("#m_del").show();#}
-	{#	$("#m_check").show();#}
-	{#	$("#m_unCheck").show();#}
-	{# }#}
     x -= 220;
     rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
 
@@ -459,7 +455,8 @@ $(document).ready(function(){
     var current_node;
     if (nodes && nodes.length ===1 ){
         current_node = nodes[0];
-        action += "?node_id=" + current_node.id;
+        action = setUrlParam(action, 'node_id', current_node.id);
+        {#action += "?node_id=" + current_node.id;#}
         $form.attr("action", action)
     }
     $form.find('.help-block').remove();
@@ -673,7 +670,45 @@ $(document).ready(function(){
             break;
     }
     $(".ipt_check_all").prop("checked", false)
-});
+})
+.on('click', '#btn_asset_modal_confirm', function () {
+    var assets_selected = asset_table2.selected;
+    var current_node;
+    var nodes = zTree.getSelectedNodes();
+    if (nodes && nodes.length === 1) {
+        current_node = nodes[0]
+    } else {
+        return
+    }
+
+    var data = {
+        'assets': assets_selected
+    };
+    var success = function () {
+        asset_table2.selected = [];
+        asset_table2.ajax.reload()
+    };
+
+    var url = '';
+    if (update_node_action === "move") {
+        url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
+    } else {
+        url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
+    }
+
+    APIUpdateAttr({
+        'url': url,
+        'method': 'PUT',
+        'body': JSON.stringify(data),
+        'success': success
+    })
+}).on('hidden.bs.modal', '#asset_list_modal', function () {
+    window.location.reload();
+}).on('click', '#menu_asset_add', function () {
+    update_node_action = "add"
+}).on('click', '#menu_asset_move', function () {
+    update_node_action = "move"
+})
 </script>
 
 {% endblock %}
\ No newline at end of file
diff --git a/apps/assets/templates/assets/domain_create_update.html b/apps/assets/templates/assets/domain_create_update.html
index 36ca40fc11bbc24050f7239a0a488e7628f4069a..3ad8724e9eac9d7a11a1fc661cf31f98d2f35e0a 100644
--- a/apps/assets/templates/assets/domain_create_update.html
+++ b/apps/assets/templates/assets/domain_create_update.html
@@ -18,14 +18,25 @@
         </div>
     </div>
 </form>
+{% include 'assets/_asset_list_modal.html' %}
 {% endblock %}
 
 {% block custom_foot_js %}
 <script type="text/javascript">
-    $(document).ready(function () {
-        $('.select2').select2({
-            closeOnSelect: false
-        });
+$(document).ready(function () {
+    console.log($.fn.select2.defaults);
+    $('.select2').select2().off("select2:open");
+}).on('click', '.select2-selection__rendered', function (e) {
+    e.preventDefault();
+    $("#asset_list_modal").modal();
+})
+.on('click', '#btn_asset_modal_confirm', function () {
+    var assets = asset_table2.selected;
+    $.each(assets, function (id, data) {
+        $('.select2').val(assets).trigger('change');
     });
+    $("#asset_list_modal").modal('hide');
+
+})
 </script>
 {% endblock %}
\ No newline at end of file
diff --git a/apps/assets/templates/assets/domain_gateway_list.html b/apps/assets/templates/assets/domain_gateway_list.html
index 3dc82652f3cb0af1b00726b5548cee7abb8285a3..581f6c08ae679623b9ae602e47d8e7de8a9a6455 100644
--- a/apps/assets/templates/assets/domain_gateway_list.html
+++ b/apps/assets/templates/assets/domain_gateway_list.html
@@ -81,11 +81,6 @@ function initTable() {
     var options = {
         ele: $('#domain_list_table'),
         columnDefs: [
-            {targets: 1, createdCell: function (td, cellData, rowData) {
-                var detail_btn = '<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
-                $(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
-             }},
-
             {targets: 7, createdCell: function (td, cellData, rowData) {
                 var update_btn = '<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
                 var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
diff --git a/apps/assets/templates/assets/label_create_update.html b/apps/assets/templates/assets/label_create_update.html
index 358faaab882b337673e5ad1fd296841d803d474e..b26ec64643387fb178b2defaf5235204a44a3014 100644
--- a/apps/assets/templates/assets/label_create_update.html
+++ b/apps/assets/templates/assets/label_create_update.html
@@ -3,6 +3,8 @@
 {% load bootstrap3 %}
 {% load i18n %}
 
+
+
 {% block form %}
 <form id="groupForm" method="post" class="form-horizontal">
     {% csrf_token %}
@@ -18,14 +20,28 @@
         </div>
     </div>
 </form>
+{% include 'assets/_asset_list_modal.html' %}
 {% endblock %}
 
 {% block custom_foot_js %}
 <script type="text/javascript">
-    $(document).ready(function () {
-        $('.select2').select2({
-            closeOnSelect: false
-        });
+$(document).ready(function () {
+    $('.select2').select2({
+        closeOnSelect: false
+    })
+}).on('click', '.select2-selection__rendered', function (e) {
+    e.preventDefault();
+    $("#asset_list_modal").modal();
+})
+.on('click', '#btn_asset_modal_confirm', function () {
+    var assets = asset_table2.selected;
+    $('.select2 option:selected').each(function (i, data) {
+        assets.push($(data).attr('value'))
+    });
+    $.each(assets, function (id, data) {
+        $('.select2').val(assets).trigger('change');
     });
+    $("#asset_list_modal").modal('hide');
+})
 </script>
 {% endblock %}
\ No newline at end of file
diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html
index 3572cfd3d18e75f7ed70c47306ebf6f3d84ee3f7..a02bf1e44e5d203a27cbff89ee4ff7f03007a998 100644
--- a/apps/assets/templates/assets/system_user_detail.html
+++ b/apps/assets/templates/assets/system_user_detail.html
@@ -173,7 +173,7 @@
                                                 <td colspan="2" class="no-borders">
                                                     <select data-placeholder="{% trans 'Add to node' %}" id="node_selected" class="select2" style="width: 100%" multiple="" tabindex="4">
                                                         {% for node in nodes_remain %}
-                                                        <option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node.name }}</option>
+                                                        <option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
@@ -187,7 +187,7 @@
 
                                         {% for node in system_user.nodes.all %}
                                         <tr>
-                                          <td ><b class="bdg_node" data-gid={{ node.id }}>{{ node.name }}</b></td>
+                                          <td ><b class="bdg_node" data-gid={{ node.id }}>{{ node }}</b></td>
                                           <td>
                                               <button class="btn btn-danger pull-right btn-xs btn-remove-from-node" type="button"><i class="fa fa-minus"></i></button>
                                           </td>
diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py
index c4925059a0eaac87f534af0ff558a9121001f7d8..4429d0f24ff8f86c85d4cfb7091b77532ae5afde 100644
--- a/apps/assets/urls/api_urls.py
+++ b/apps/assets/urls/api_urls.py
@@ -40,6 +40,7 @@ urlpatterns = [
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'),
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.NodeAssetsApi.as_view(), name='node-assets'),
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
+    url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/replace/$', api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'),
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
     url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py
index 953f3c8acb55ac7e8d90272e14ba9cc6020df7be..306a26a0aa3e11c1faccc74f7f61ab3ae2eec3ff 100644
--- a/apps/assets/views/asset.py
+++ b/apps/assets/views/asset.py
@@ -49,6 +49,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
             'app': _('Assets'),
             'action': _('Asset list'),
             'labels': Label.objects.all().order_by('name'),
+            'nodes': Node.objects.all().order_by('-key'),
         }
         kwargs.update(context)
         return super().get_context_data(**kwargs)
@@ -284,24 +285,26 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
             if set(row) == {''}:
                 continue
 
-            asset_dict = dict(zip(attr, row))
-            id_ = asset_dict.pop('id', 0)
-            for k, v in asset_dict.items():
+            asset_dict_raw = dict(zip(attr, row))
+            asset_dict = dict()
+            for k, v in asset_dict_raw.items():
                 v = v.strip()
                 if k == 'is_active':
-                    v = True if v in ['TRUE', 1, 'true'] else False
+                    v = False if v in ['False', 0, 'false'] else True
                 elif k == 'admin_user':
                     v = get_object_or_none(AdminUser, name=v)
                 elif k in ['port', 'cpu_count', 'cpu_cores']:
                     try:
                         v = int(v)
                     except ValueError:
-                        v = 0
+                        v = ''
                 elif k == 'domain':
                     v = get_object_or_none(Domain, name=v)
-                asset_dict[k] = v
 
-            asset = get_object_or_none(Asset, id=id_) if is_uuid(id_) else None
+                if v != '':
+                    asset_dict[k] = v
+
+            asset = get_object_or_none(Asset, id=asset_dict.pop('id', 0))
             if not asset:
                 try:
                     if len(Asset.objects.filter(hostname=asset_dict.get('hostname'))):
@@ -316,7 +319,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
                     failed.append('%s: %s' % (asset_dict['hostname'], str(e)))
             else:
                 for k, v in asset_dict.items():
-                    if v:
+                    if v != '':
                         setattr(asset, k, v)
                 try:
                     asset.save()
diff --git a/apps/common/fields.py b/apps/common/fields.py
index a06106cfaf29cb710264abbecd85b4d499773cb7..355344cd961b50033ef9eeb88eb475420424377e 100644
--- a/apps/common/fields.py
+++ b/apps/common/fields.py
@@ -2,11 +2,15 @@
 #
 import json
 
+from django.db import models
 from django import forms
 from django.utils import six
 from django.core.exceptions import ValidationError
 from django.utils.translation import ugettext as _
 from rest_framework import serializers
+from .utils import get_signer
+
+signer = get_signer()
 
 
 class DictField(forms.Field):
@@ -46,4 +50,27 @@ class StringIDField(serializers.Field):
 
 class StringManyToManyField(serializers.RelatedField):
     def to_representation(self, value):
-        return value.__str__()
\ No newline at end of file
+        return value.__str__()
+
+
+class EncryptMixin:
+    def from_db_value(self, value, expression, connection, context):
+        if value is not None:
+            return signer.unsign(value)
+        return super().from_db_value(self, value, expression, connection, context)
+
+    def get_prep_value(self, value):
+        if value is None:
+            return value
+        return signer.sign(value).decode('utf-8')
+
+
+class EncryptTextField(EncryptMixin, models.TextField):
+    description = _("Encrypt field using Secret Key")
+
+
+class EncryptCharField(EncryptMixin, models.CharField):
+    def __init__(self, *args, **kwargs):
+        kwargs['max_length'] = 2048
+        super().__init__(*args, **kwargs)
+
diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo
index 61ef6ec21bb6059e9edbfaf75676af11deac619e..a343d985af7dfd3579a03d47852c15e6b2e7ed68 100644
Binary files a/apps/i18n/zh/LC_MESSAGES/django.mo and b/apps/i18n/zh/LC_MESSAGES/django.mo differ
diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po
index fc8255313d0d747c78587655069df6dd2ce11b7a..5c559f24e3b3dedcdfd6ce6ee5743df5f8d1c99c 100644
--- a/apps/i18n/zh/LC_MESSAGES/django.po
+++ b/apps/i18n/zh/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Jumpserver 0.3.3\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-04-06 10:24+0800\n"
+"POT-Creation-Date: 2018-04-13 17:27+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: ibuler <ibuler@qq.com>\n"
 "Language-Team: Jumpserver team<ibuler@qq.com>\n"
@@ -17,45 +17,57 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: assets/api/node.py:58
+#: assets/api/node.py:88
 msgid "New node {}"
 msgstr "新节点 {}"
 
-#: assets/api/node.py:133
+#: assets/api/node.py:216
 msgid "更新节点资产硬件信息: {}"
 msgstr ""
 
-#: assets/api/node.py:146
+#: assets/api/node.py:229
 msgid "测试节点下资产是否可连接: {}"
 msgstr ""
 
-#: assets/forms/asset.py:24 assets/forms/asset.py:60 assets/models/asset.py:53
-#: assets/models/user.py:102 assets/templates/assets/asset_detail.html:183
+#: assets/forms/asset.py:24 assets/models/asset.py:54 assets/models/user.py:103
+#: assets/templates/assets/asset_detail.html:183
 #: assets/templates/assets/asset_detail.html:191
-#: assets/templates/assets/system_user_detail.html:166
+#: assets/templates/assets/system_user_detail.html:166 perms/models.py:23
 msgid "Nodes"
 msgstr "节点管理"
 
-#: assets/forms/asset.py:27 assets/forms/asset.py:63 assets/forms/asset.py:103
-#: assets/forms/asset.py:107 assets/models/asset.py:57
-#: assets/models/cluster.py:19 assets/models/user.py:71
+#: assets/forms/asset.py:27 assets/forms/asset.py:66 assets/forms/asset.py:109
+#: assets/forms/asset.py:113 assets/models/asset.py:58
+#: assets/models/cluster.py:19 assets/models/user.py:72
 #: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25
 msgid "Admin user"
 msgstr "管理用户"
 
-#: assets/forms/asset.py:30 assets/forms/asset.py:66 assets/models/asset.py:81
-#: assets/templates/assets/asset_create.html:33
-#: assets/templates/assets/asset_detail.html:220
-#: assets/templates/assets/asset_update.html:38 templates/_nav.html:27
-msgid "Labels"
-msgstr "标签管理"
+#: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:125
+#: assets/templates/assets/asset_create.html:35
+#: assets/templates/assets/asset_create.html:37
+#: assets/templates/assets/asset_list.html:75
+#: assets/templates/assets/asset_update.html:40
+#: assets/templates/assets/asset_update.html:42
+#: assets/templates/assets/user_asset_list.html:34
+msgid "Label"
+msgstr "标签"
 
-#: assets/forms/asset.py:34 assets/forms/asset.py:70 assets/models/asset.py:52
+#: assets/forms/asset.py:34 assets/forms/asset.py:73 assets/models/asset.py:53
 #: assets/models/domain.py:46
 msgid "Domain"
 msgstr "网域"
 
-#: assets/forms/asset.py:42 assets/forms/asset.py:79
+#: assets/forms/asset.py:38 assets/forms/asset.py:63 assets/forms/asset.py:77
+#: assets/forms/asset.py:128 assets/templates/assets/asset_create.html:29
+#: assets/templates/assets/asset_update.html:34 perms/forms.py:40
+#: perms/forms.py:47 perms/models.py:67
+#: perms/templates/perms/asset_permission_list.html:57
+#: perms/templates/perms/asset_permission_list.html:142
+msgid "Node"
+msgstr "节点"
+
+#: assets/forms/asset.py:45 assets/forms/asset.py:85
 msgid ""
 "root or other NOPASSWD sudo privilege user existed in asset,If asset is "
 "windows or other set any one, more see admin user left menu"
@@ -63,46 +75,41 @@ msgstr ""
 "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
 "个, 更多信息查看左侧 `管理用户` 菜单"
 
-#: assets/forms/asset.py:45 assets/forms/asset.py:82
+#: assets/forms/asset.py:48 assets/forms/asset.py:88
 msgid "* required Must set exact system platform, Windows, Linux ..."
 msgstr "* required 必须准确设置操作系统平台,如Windows, Linux ..."
 
-#: assets/forms/asset.py:46 assets/forms/asset.py:83
+#: assets/forms/asset.py:49 assets/forms/asset.py:89
 msgid ""
 "If your have some network not connect with each other, you can set domain"
 msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
 
-#: assets/forms/asset.py:90 assets/forms/asset.py:94 assets/forms/domain.py:16
+#: assets/forms/asset.py:96 assets/forms/asset.py:100 assets/forms/domain.py:16
 #: assets/forms/label.py:15
-#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:272
+#: perms/templates/perms/asset_permission_asset.html:88
 msgid "Select assets"
 msgstr "选择资产"
 
-#: assets/forms/asset.py:99 assets/models/asset.py:51
+#: assets/forms/asset.py:105 assets/models/asset.py:51
 #: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53
 #: assets/templates/assets/asset_detail.html:69
 #: assets/templates/assets/domain_gateway_list.html:58
 #: assets/templates/assets/system_user_asset.html:51
-#: assets/templates/assets/user_asset_list.html:21
 msgid "Port"
 msgstr "端口"
 
-#: assets/forms/asset.py:119 assets/templates/assets/asset_create.html:37
-msgid "Select labels"
-msgstr "选择标签"
-
-#: assets/forms/asset.py:122 assets/templates/assets/admin_user_detail.html:91
-msgid "Select nodes"
-msgstr "选择节点"
-
 #: assets/forms/domain.py:14 assets/forms/label.py:13
-#: assets/models/asset.py:165 assets/templates/assets/admin_user_list.html:25
+#: assets/models/asset.py:169 assets/templates/assets/admin_user_list.html:25
 #: assets/templates/assets/domain_detail.html:60
 #: assets/templates/assets/domain_list.html:15
 #: assets/templates/assets/label_list.html:16
 #: assets/templates/assets/system_user_list.html:29 audits/models.py:11
 #: audits/templates/audits/ftp_log_list.html:41
-#: audits/templates/audits/ftp_log_list.html:72 perms/models.py:17
+#: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:37
+#: perms/models.py:22
+#: perms/templates/perms/asset_permission_create_update.html:40
+#: perms/templates/perms/asset_permission_list.html:56
+#: perms/templates/perms/asset_permission_list.html:139
 #: terminal/backends/command/models.py:11 terminal/models.py:123
 #: terminal/templates/terminal/command_list.html:40
 #: terminal/templates/terminal/command_list.html:73
@@ -125,11 +132,12 @@ msgstr "资产"
 #: common/templates/common/terminal_setting.html:67
 #: common/templates/common/terminal_setting.html:85 ops/models/adhoc.py:36
 #: ops/templates/ops/task_detail.html:59 ops/templates/ops/task_list.html:35
-#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
+#: perms/models.py:19 perms/templates/perms/asset_permission_detail.html:62
+#: perms/templates/perms/asset_permission_list.html:53
 #: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
 #: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
 #: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
-#: users/models/user.py:35 users/templates/users/_select_user_modal.html:13
+#: users/models/user.py:40 users/templates/users/_select_user_modal.html:13
 #: users/templates/users/user_detail.html:63
 #: users/templates/users/user_group_detail.html:55
 #: users/templates/users/user_group_list.html:12
@@ -145,8 +153,8 @@ msgstr "名称"
 #: assets/templates/assets/domain_gateway_list.html:60
 #: assets/templates/assets/system_user_detail.html:62
 #: assets/templates/assets/system_user_list.html:27
-#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14
-#: users/models/authentication.py:45 users/models/user.py:34
+#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:13
+#: users/models/authentication.py:45 users/models/user.py:39
 #: users/templates/users/_select_user_modal.html:14
 #: users/templates/users/login.html:56
 #: users/templates/users/login_log_list.html:49
@@ -161,7 +169,7 @@ msgid "Password or private key passphrase"
 msgstr "密码或密钥密码"
 
 #: assets/forms/user.py:25 assets/models/base.py:22 common/forms.py:113
-#: users/forms.py:16 users/forms.py:25 users/templates/users/login.html:59
+#: users/forms.py:15 users/forms.py:24 users/templates/users/login.html:59
 #: users/templates/users/reset_password.html:52
 #: users/templates/users/user_create.html:11
 #: users/templates/users/user_password_update.html:40
@@ -170,7 +178,7 @@ msgstr "密码或密钥密码"
 msgid "Password"
 msgstr "密码"
 
-#: assets/forms/user.py:28 users/models/user.py:45
+#: assets/forms/user.py:28 users/models/user.py:50
 msgid "Private key"
 msgstr "ssh私钥"
 
@@ -193,13 +201,13 @@ msgid ""
 msgstr "高优先级的系统用户将会作为默认登录用户"
 
 #: assets/models/asset.py:49 assets/models/domain.py:43
-#: assets/templates/assets/_asset_list_modal.html:21
+#: assets/templates/assets/_asset_list_modal.html:46
 #: assets/templates/assets/admin_user_assets.html:52
 #: assets/templates/assets/asset_detail.html:61
 #: assets/templates/assets/asset_list.html:87
 #: assets/templates/assets/domain_gateway_list.html:57
 #: assets/templates/assets/system_user_asset.html:50
-#: assets/templates/assets/user_asset_list.html:20 common/forms.py:144
+#: assets/templates/assets/user_asset_list.html:46 common/forms.py:144
 #: perms/templates/perms/asset_permission_asset.html:55
 #: users/templates/users/login_log_list.html:52
 #: users/templates/users/user_granted_asset.html:45
@@ -207,72 +215,71 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
 msgid "IP"
 msgstr "IP"
 
-#: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:20
+#: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:45
 #: assets/templates/assets/admin_user_assets.html:51
 #: assets/templates/assets/asset_detail.html:57
 #: assets/templates/assets/asset_list.html:86
 #: assets/templates/assets/system_user_asset.html:49
-#: assets/templates/assets/user_asset_list.html:19 common/forms.py:143
+#: assets/templates/assets/user_asset_list.html:45 common/forms.py:143
 #: perms/templates/perms/asset_permission_asset.html:54
 #: users/templates/users/user_granted_asset.html:44
 #: users/templates/users/user_group_granted_asset.html:44
 msgid "Hostname"
 msgstr "主机名"
 
-#: assets/models/asset.py:54 assets/models/domain.py:48
+#: assets/models/asset.py:52 assets/templates/assets/asset_detail.html:97
+msgid "Platform"
+msgstr "系统平台"
+
+#: assets/models/asset.py:55 assets/models/domain.py:48
 #: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
-#: perms/templates/perms/asset_permission_list.html:70
 msgid "Is active"
 msgstr "激活"
 
-#: assets/models/asset.py:60 assets/templates/assets/asset_detail.html:65
+#: assets/models/asset.py:61 assets/templates/assets/asset_detail.html:65
 msgid "Public IP"
 msgstr "公网IP"
 
-#: assets/models/asset.py:61 assets/templates/assets/asset_detail.html:113
+#: assets/models/asset.py:62 assets/templates/assets/asset_detail.html:113
 msgid "Asset number"
 msgstr "资产编号"
 
-#: assets/models/asset.py:64 assets/templates/assets/asset_detail.html:77
+#: assets/models/asset.py:65 assets/templates/assets/asset_detail.html:77
 msgid "Vendor"
 msgstr "制造商"
 
-#: assets/models/asset.py:65 assets/templates/assets/asset_detail.html:81
+#: assets/models/asset.py:66 assets/templates/assets/asset_detail.html:81
 msgid "Model"
 msgstr "型号"
 
-#: assets/models/asset.py:66 assets/templates/assets/asset_detail.html:109
+#: assets/models/asset.py:67 assets/templates/assets/asset_detail.html:109
 msgid "Serial number"
 msgstr "序列号"
 
-#: assets/models/asset.py:68
+#: assets/models/asset.py:69
 msgid "CPU model"
 msgstr "CPU型号"
 
-#: assets/models/asset.py:69
+#: assets/models/asset.py:70
 msgid "CPU count"
 msgstr "CPU数量"
 
-#: assets/models/asset.py:70
+#: assets/models/asset.py:71
 msgid "CPU cores"
 msgstr "CPU核数"
 
-#: assets/models/asset.py:71 assets/templates/assets/asset_detail.html:89
+#: assets/models/asset.py:72 assets/templates/assets/asset_detail.html:89
 msgid "Memory"
 msgstr "内存"
 
-#: assets/models/asset.py:72
+#: assets/models/asset.py:73
 msgid "Disk total"
 msgstr "硬盘大小"
 
-#: assets/models/asset.py:73
+#: assets/models/asset.py:74
 msgid "Disk info"
 msgstr "硬盘信息"
 
-#: assets/models/asset.py:75 assets/templates/assets/asset_detail.html:97
-msgid "Platform"
-msgstr "系统平台"
-
 #: assets/models/asset.py:76 assets/templates/assets/asset_detail.html:101
 msgid "OS"
 msgstr "操作系统"
@@ -289,15 +296,21 @@ msgstr "系统架构"
 msgid "Hostname raw"
 msgstr "主机名原始"
 
+#: assets/models/asset.py:81 assets/templates/assets/asset_create.html:33
+#: assets/templates/assets/asset_detail.html:220
+#: assets/templates/assets/asset_update.html:38 templates/_nav.html:27
+msgid "Labels"
+msgstr "标签管理"
+
 #: assets/models/asset.py:82 assets/models/base.py:28
 #: assets/models/cluster.py:28 assets/models/group.py:21
 #: assets/templates/assets/admin_user_detail.html:68
 #: assets/templates/assets/asset_detail.html:117
 #: assets/templates/assets/domain_detail.html:72
 #: assets/templates/assets/system_user_detail.html:96
-#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:22 perms/models.py:79
-#: perms/templates/perms/asset_permission_detail.html:94
-#: users/models/user.py:50 users/templates/users/user_detail.html:99
+#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:28 perms/models.py:72
+#: perms/templates/perms/asset_permission_detail.html:98
+#: users/models/user.py:55 users/templates/users/user_detail.html:99
 msgid "Created by"
 msgstr "创建者"
 
@@ -307,8 +320,8 @@ msgstr "创建者"
 #: assets/templates/assets/domain_detail.html:68
 #: assets/templates/assets/system_user_detail.html:92
 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63
-#: perms/models.py:23 perms/models.py:80
-#: perms/templates/perms/asset_permission_detail.html:90
+#: perms/models.py:29 perms/models.py:73
+#: perms/templates/perms/asset_permission_detail.html:94
 #: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
 #: users/templates/users/user_group_detail.html:63
 msgid "Date created"
@@ -325,10 +338,10 @@ msgstr "创建日期"
 #: assets/templates/assets/domain_list.html:17
 #: assets/templates/assets/system_user_detail.html:100
 #: assets/templates/assets/system_user_list.html:33 common/models.py:30
-#: ops/models/adhoc.py:42 perms/models.py:24 perms/models.py:81
-#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
+#: ops/models/adhoc.py:42 perms/models.py:30 perms/models.py:74
+#: perms/templates/perms/asset_permission_detail.html:102 terminal/models.py:26
 #: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
-#: users/models/user.py:47 users/templates/users/user_detail.html:111
+#: users/models/user.py:52 users/templates/users/user_detail.html:111
 #: users/templates/users/user_group_detail.html:67
 #: users/templates/users/user_group_list.html:14
 #: users/templates/users/user_profile.html:114
@@ -351,7 +364,7 @@ msgstr "带宽"
 msgid "Contact"
 msgstr "联系人"
 
-#: assets/models/cluster.py:22 users/models/user.py:41
+#: assets/models/cluster.py:22 users/models/user.py:46
 #: users/templates/users/user_detail.html:76
 msgid "Phone"
 msgstr "手机"
@@ -377,7 +390,7 @@ msgid "Default"
 msgstr "默认"
 
 #: assets/models/cluster.py:36 assets/models/label.py:13
-#: users/models/user.py:266
+#: users/models/user.py:285
 msgid "System"
 msgstr "系统"
 
@@ -389,14 +402,14 @@ msgstr "默认Cluster"
 msgid "Cluster"
 msgstr "集群"
 
-#: assets/models/domain.py:45 assets/models/user.py:104
+#: assets/models/domain.py:45 assets/models/user.py:106
 #: assets/templates/assets/domain_gateway_list.html:59
 #: assets/templates/assets/system_user_detail.html:66
 #: assets/templates/assets/system_user_list.html:28
 msgid "Protocol"
 msgstr "协议"
 
-#: assets/models/group.py:30 perms/models.py:18
+#: assets/models/group.py:30
 msgid "Asset group"
 msgstr "资产组"
 
@@ -406,15 +419,19 @@ msgstr "默认资产组"
 
 #: assets/models/label.py:14 audits/models.py:9
 #: audits/templates/audits/ftp_log_list.html:33
-#: audits/templates/audits/ftp_log_list.html:71 perms/models.py:15
+#: audits/templates/audits/ftp_log_list.html:71 perms/forms.py:14
+#: perms/forms.py:31 perms/models.py:20
+#: perms/templates/perms/asset_permission_create_update.html:36
+#: perms/templates/perms/asset_permission_list.html:54
+#: perms/templates/perms/asset_permission_list.html:133
 #: terminal/backends/command/models.py:10 terminal/models.py:122
 #: terminal/templates/terminal/command_list.html:32
 #: terminal/templates/terminal/command_list.html:72
 #: terminal/templates/terminal/session_list.html:33
-#: terminal/templates/terminal/session_list.html:71 users/forms.py:220
-#: users/models/user.py:30 users/models/user.py:254
+#: terminal/templates/terminal/session_list.html:71 users/forms.py:219
+#: users/models/user.py:30 users/models/user.py:273
 #: users/templates/users/user_group_detail.html:78
-#: users/templates/users/user_group_list.html:13 users/views/user.py:334
+#: users/templates/users/user_group_list.html:13 users/views/user.py:335
 msgid "User"
 msgstr "用户"
 
@@ -431,30 +448,49 @@ msgstr "分类"
 msgid "Key"
 msgstr ""
 
-#: assets/models/user.py:103
+#: assets/models/user.py:104
+#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
+#: assets/templates/assets/system_user_asset.html:21
+#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
+#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
+#: assets/views/admin_user.py:102 assets/views/asset.py:49
+#: assets/views/asset.py:96 assets/views/asset.py:156 assets/views/asset.py:173
+#: assets/views/asset.py:197 assets/views/domain.py:29
+#: assets/views/domain.py:45 assets/views/domain.py:61
+#: assets/views/domain.py:74 assets/views/domain.py:98
+#: assets/views/domain.py:126 assets/views/domain.py:150
+#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58
+#: assets/views/system_user.py:28 assets/views/system_user.py:44
+#: assets/views/system_user.py:60 assets/views/system_user.py:74
+#: templates/_nav.html:20
+msgid "Assets"
+msgstr "资产管理"
+
+#: assets/models/user.py:105
 msgid "Priority"
 msgstr "优先级"
 
-#: assets/models/user.py:105 assets/templates/assets/_system_user.html:58
+#: assets/models/user.py:107 assets/templates/assets/_system_user.html:58
 #: assets/templates/assets/system_user_detail.html:118
 #: assets/templates/assets/system_user_update.html:11
 msgid "Auto push"
 msgstr "自动推送"
 
-#: assets/models/user.py:106 assets/templates/assets/system_user_detail.html:70
+#: assets/models/user.py:108 assets/templates/assets/system_user_detail.html:70
 msgid "Sudo"
 msgstr "Sudo"
 
-#: assets/models/user.py:107 assets/templates/assets/system_user_detail.html:75
+#: assets/models/user.py:109 assets/templates/assets/system_user_detail.html:75
 msgid "Shell"
 msgstr "Shell"
 
-#: assets/models/user.py:150 audits/models.py:12
+#: assets/models/user.py:149 audits/models.py:12
 #: audits/templates/audits/ftp_log_list.html:49
-#: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:25
-#: perms/models.py:19 perms/models.py:76
-#: perms/templates/perms/asset_permission_detail.html:136
-#: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:26
+#: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:43
+#: perms/models.py:24 perms/models.py:69
+#: perms/templates/perms/asset_permission_detail.html:140
+#: perms/templates/perms/asset_permission_list.html:58
+#: perms/templates/perms/asset_permission_list.html:145 templates/_nav.html:26
 #: terminal/backends/command/models.py:12 terminal/models.py:124
 #: terminal/templates/terminal/command_list.html:48
 #: terminal/templates/terminal/command_list.html:74
@@ -468,41 +504,65 @@ msgstr "系统用户"
 msgid "%(value)s is not an even number"
 msgstr "%(value)s is not an even number"
 
-#: assets/tasks.py:96 assets/tasks.py:113
+#: assets/tasks.py:96 assets/tasks.py:116
 msgid "更新资产硬件信息"
 msgstr ""
 
-#: assets/tasks.py:132
+#: assets/tasks.py:135
 msgid "定期更新资产硬件信息"
 msgstr ""
 
-#: assets/tasks.py:210
+#: assets/tasks.py:213
 msgid "定期测试管理账号可连接性: {}"
 msgstr ""
 
-#: assets/tasks.py:217
+#: assets/tasks.py:220
 msgid "测试管理行号可连接性: {}"
 msgstr ""
 
-#: assets/tasks.py:227
+#: assets/tasks.py:230
 msgid "测试资产可连接性"
 msgstr ""
 
-#: assets/tasks.py:297
+#: assets/tasks.py:300
 msgid "Test system user connectability: {}"
 msgstr "测试系统用户可连接性: {}"
 
-#: assets/tasks.py:313
+#: assets/tasks.py:316
 msgid "定期测试系统用户可连接性: {}"
 msgstr ""
 
-#: assets/tasks.py:392
-msgid "推送系统用户到节点资产: {} => {}"
+#: assets/tasks.py:401
+msgid "推送系统用户到入资产: {}"
 msgstr ""
 
-#: assets/tasks.py:433
-msgid "推送节点系统用户到新加入资产中: {}"
-msgstr ""
+#: assets/templates/assets/_admin_user_setting_modal.html:4
+#: users/templates/users/reset_password.html:57
+#: users/templates/users/user_profile.html:20
+msgid "Setting"
+msgstr "设置"
+
+#: assets/templates/assets/_admin_user_setting_modal.html:9
+#: assets/templates/assets/_asset_import_modal.html:9
+#: users/templates/users/_user_import_modal.html:10
+msgid "Template"
+msgstr "模板"
+
+#: assets/templates/assets/_admin_user_setting_modal.html:10
+#: assets/templates/assets/_asset_import_modal.html:10
+#: users/templates/users/_user_import_modal.html:11
+msgid "Download"
+msgstr "下载"
+
+#: assets/templates/assets/_admin_user_setting_modal.html:13
+#: assets/templates/assets/_asset_import_modal.html:13
+msgid "Asset csv file"
+msgstr "资产csv文件"
+
+#: assets/templates/assets/_admin_user_setting_modal.html:16
+#: assets/templates/assets/_asset_import_modal.html:16
+msgid "If set id, will use this id update asset existed"
+msgstr "如果设置了id,则会使用该行信息更新该id的资产"
 
 #: assets/templates/assets/_asset_group_bulk_update_modal.html:5
 msgid "Update asset group"
@@ -512,28 +572,13 @@ msgstr "更新用户组"
 msgid "Hint: only change the field you want to update."
 msgstr "仅修改你需要更新的字段"
 
-#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
-#: assets/templates/assets/system_user_asset.html:21
-#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
-#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
-#: assets/views/admin_user.py:102 assets/views/asset.py:49
-#: assets/views/asset.py:95 assets/views/asset.py:155 assets/views/asset.py:172
-#: assets/views/asset.py:196 assets/views/domain.py:29
-#: assets/views/domain.py:45 assets/views/domain.py:61
-#: assets/views/domain.py:74 assets/views/domain.py:98
-#: assets/views/domain.py:126 assets/views/domain.py:150
-#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58
-#: assets/views/system_user.py:28 assets/views/system_user.py:44
-#: assets/views/system_user.py:60 assets/views/system_user.py:74
-#: templates/_nav.html:20
-msgid "Assets"
-msgstr "资产管理"
-
 #: assets/templates/assets/_asset_group_bulk_update_modal.html:13
 msgid "Select Asset"
 msgstr "选择资产"
 
 #: assets/templates/assets/_asset_group_bulk_update_modal.html:21
+#: assets/templates/assets/user_asset_list.html:48
+#: users/templates/users/user_granted_asset.html:47
 msgid "System users"
 msgstr "系统用户"
 
@@ -549,181 +594,16 @@ msgstr "二次验证"
 msgid "Import asset"
 msgstr "导入资产"
 
-#: assets/templates/assets/_asset_import_modal.html:9
-#: users/templates/users/_user_import_modal.html:10
-msgid "Template"
-msgstr "模板"
-
-#: assets/templates/assets/_asset_import_modal.html:10
-#: users/templates/users/_user_import_modal.html:11
-msgid "Download"
-msgstr "下载"
-
-#: assets/templates/assets/_asset_import_modal.html:13
-msgid "Asset csv file"
-msgstr "资产csv文件"
-
-#: assets/templates/assets/_asset_import_modal.html:16
-msgid "If set id, will use this id update asset existed"
-msgstr "如果设置了id,则会使用该行信息更新该id的资产"
-
-#: assets/templates/assets/_asset_list_modal.html:22
-#: assets/templates/assets/asset_list.html:88
-#: assets/templates/assets/user_asset_list.html:22
-msgid "Hardware"
-msgstr "硬件"
-
-#: assets/templates/assets/_asset_list_modal.html:23
-#: assets/templates/assets/asset_detail.html:143
-#: assets/templates/assets/asset_list.html:89
-#: assets/templates/assets/user_asset_list.html:23 perms/models.py:20
-#: perms/models.py:77
-#: perms/templates/perms/asset_permission_create_update.html:51
-#: perms/templates/perms/asset_permission_detail.html:116
-#: terminal/templates/terminal/terminal_list.html:34
-#: users/templates/users/_select_user_modal.html:18
-#: users/templates/users/user_detail.html:128
-#: users/templates/users/user_granted_asset.html:46
-#: users/templates/users/user_group_granted_asset.html:46
-#: users/templates/users/user_list.html:27
-#: users/templates/users/user_profile.html:63
-msgid "Active"
-msgstr "激活中"
-
-#: assets/templates/assets/_asset_list_modal.html:24
-#: assets/templates/assets/admin_user_assets.html:54
-#: assets/templates/assets/admin_user_list.html:26
-#: assets/templates/assets/asset_list.html:90
-#: assets/templates/assets/system_user_asset.html:52
-#: assets/templates/assets/system_user_list.html:30
-#: users/templates/users/user_granted_asset.html:47
-#: users/templates/users/user_group_granted_asset.html:47
-msgid "Reachable"
-msgstr "可连接"
-
-#: assets/templates/assets/_asset_list_modal.html:25
-#: assets/templates/assets/admin_user_list.html:30
-#: assets/templates/assets/asset_list.html:91
-#: assets/templates/assets/domain_gateway_list.html:62
-#: assets/templates/assets/domain_list.html:18
-#: assets/templates/assets/label_list.html:17
-#: assets/templates/assets/system_user_list.html:34
-#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
-#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
-#: perms/templates/perms/asset_permission_list.html:72
-#: terminal/templates/terminal/session_list.html:80
-#: terminal/templates/terminal/terminal_list.html:36
-#: users/templates/users/user_group_list.html:15
-#: users/templates/users/user_list.html:28
-msgid "Action"
-msgstr "动作"
-
-#: assets/templates/assets/_asset_list_modal.html:34
-#: assets/templates/assets/asset_list.html:100
-#: users/templates/users/user_list.html:37
-msgid "Delete selected"
-msgstr "批量删除"
-
-#: assets/templates/assets/_asset_list_modal.html:35
-#: assets/templates/assets/asset_list.html:101
-#: users/templates/users/user_list.html:38
-msgid "Update selected"
-msgstr "批量更新"
-
-#: assets/templates/assets/_asset_list_modal.html:36
-#: assets/templates/assets/asset_list.html:103
-#: users/templates/users/user_list.html:39
-msgid "Deactive selected"
-msgstr "禁用所选"
-
-#: assets/templates/assets/_asset_list_modal.html:37
-#: assets/templates/assets/asset_list.html:104
-#: users/templates/users/user_list.html:40
-msgid "Active selected"
-msgstr "激活所选"
-
-#: assets/templates/assets/_asset_list_modal.html:41
-#: assets/templates/assets/_system_user.html:71
-#: assets/templates/assets/admin_user_create_update.html:46
-#: assets/templates/assets/asset_bulk_update.html:24
-#: assets/templates/assets/asset_create.html:67
-#: assets/templates/assets/asset_list.html:108
-#: assets/templates/assets/asset_update.html:71
-#: assets/templates/assets/domain_create_update.html:17
-#: assets/templates/assets/gateway_create_update.html:59
-#: assets/templates/assets/label_create_update.html:17
-#: common/templates/common/basic_setting.html:59
-#: common/templates/common/email_setting.html:60
-#: common/templates/common/ldap_setting.html:60
-#: common/templates/common/terminal_setting.html:103
-#: perms/templates/perms/asset_permission_create_update.html:72
-#: terminal/templates/terminal/session_list.html:120
-#: terminal/templates/terminal/terminal_update.html:48
-#: users/templates/users/_user.html:44
-#: users/templates/users/first_login.html:62
-#: users/templates/users/forgot_password.html:44
-#: users/templates/users/user_bulk_update.html:24
-#: users/templates/users/user_list.html:44
-#: users/templates/users/user_password_update.html:59
-#: users/templates/users/user_profile_update.html:64
-#: users/templates/users/user_pubkey_update.html:77
-msgid "Submit"
-msgstr "提交"
-
-#: assets/templates/assets/_asset_list_modal.html:79
-#: assets/templates/assets/admin_user_detail.html:24
-#: assets/templates/assets/admin_user_list.html:85
-#: assets/templates/assets/asset_detail.html:24
-#: assets/templates/assets/asset_list.html:168
-#: assets/templates/assets/domain_detail.html:24
-#: assets/templates/assets/domain_detail.html:103
-#: assets/templates/assets/domain_gateway_list.html:90
-#: assets/templates/assets/domain_list.html:42
-#: assets/templates/assets/label_list.html:38
-#: assets/templates/assets/system_user_detail.html:26
-#: assets/templates/assets/system_user_list.html:88
-#: perms/templates/perms/asset_permission_detail.html:30
-#: perms/templates/perms/asset_permission_list.html:121
-#: terminal/templates/terminal/terminal_detail.html:16
-#: terminal/templates/terminal/terminal_list.html:71
-#: users/templates/users/user_detail.html:25
-#: users/templates/users/user_group_detail.html:28
-#: users/templates/users/user_group_list.html:43
-#: users/templates/users/user_list.html:76
-#: users/templates/users/user_profile.html:135
-#: users/templates/users/user_profile.html:143
-msgid "Update"
-msgstr "æ›´æ–°"
-
-#: assets/templates/assets/_asset_list_modal.html:80
-#: assets/templates/assets/admin_user_detail.html:28
-#: assets/templates/assets/admin_user_list.html:86
-#: assets/templates/assets/asset_detail.html:28
-#: assets/templates/assets/asset_list.html:169
-#: assets/templates/assets/domain_detail.html:28
-#: assets/templates/assets/domain_detail.html:104
-#: assets/templates/assets/domain_gateway_list.html:91
-#: assets/templates/assets/domain_list.html:43
-#: assets/templates/assets/label_list.html:39
-#: assets/templates/assets/system_user_detail.html:30
-#: assets/templates/assets/system_user_list.html:89
-#: ops/templates/ops/task_list.html:72
-#: perms/templates/perms/asset_permission_detail.html:34
-#: perms/templates/perms/asset_permission_list.html:122
-#: terminal/templates/terminal/terminal_list.html:73
-#: users/templates/users/user_detail.html:30
-#: users/templates/users/user_group_detail.html:32
-#: users/templates/users/user_group_list.html:45
-#: users/templates/users/user_list.html:80
-#: users/templates/users/user_list.html:84
-msgid "Delete"
-msgstr "删除"
+#: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:50
+#: templates/_nav.html:23
+msgid "Asset list"
+msgstr "资产列表"
 
 #: assets/templates/assets/_system_user.html:37
 #: assets/templates/assets/asset_create.html:16
 #: assets/templates/assets/asset_update.html:21
 #: assets/templates/assets/gateway_create_update.html:37
-#: perms/templates/perms/asset_permission_create_update.html:38
+#: perms/templates/perms/asset_permission_create_update.html:33
 msgid "Basic"
 msgstr "基本"
 
@@ -745,7 +625,7 @@ msgstr "自动生成密钥"
 #: assets/templates/assets/asset_create.html:59
 #: assets/templates/assets/asset_update.html:63
 #: assets/templates/assets/gateway_create_update.html:53
-#: perms/templates/perms/asset_permission_create_update.html:49
+#: perms/templates/perms/asset_permission_create_update.html:45
 #: terminal/templates/terminal/terminal_update.html:42
 msgid "Other"
 msgstr "其它"
@@ -762,7 +642,7 @@ msgstr "其它"
 #: common/templates/common/email_setting.html:59
 #: common/templates/common/ldap_setting.html:59
 #: common/templates/common/terminal_setting.html:101
-#: perms/templates/perms/asset_permission_create_update.html:71
+#: perms/templates/perms/asset_permission_create_update.html:69
 #: terminal/templates/terminal/terminal_update.html:47
 #: users/templates/users/_user.html:43
 #: users/templates/users/user_bulk_update.html:23
@@ -774,6 +654,33 @@ msgstr "其它"
 msgid "Reset"
 msgstr "重置"
 
+#: assets/templates/assets/_system_user.html:71
+#: assets/templates/assets/admin_user_create_update.html:46
+#: assets/templates/assets/asset_bulk_update.html:24
+#: assets/templates/assets/asset_create.html:67
+#: assets/templates/assets/asset_list.html:108
+#: assets/templates/assets/asset_update.html:71
+#: assets/templates/assets/domain_create_update.html:17
+#: assets/templates/assets/gateway_create_update.html:59
+#: assets/templates/assets/label_create_update.html:17
+#: common/templates/common/basic_setting.html:59
+#: common/templates/common/email_setting.html:60
+#: common/templates/common/ldap_setting.html:60
+#: common/templates/common/terminal_setting.html:103
+#: perms/templates/perms/asset_permission_create_update.html:70
+#: terminal/templates/terminal/session_list.html:120
+#: terminal/templates/terminal/terminal_update.html:48
+#: users/templates/users/_user.html:44
+#: users/templates/users/first_login.html:62
+#: users/templates/users/forgot_password.html:44
+#: users/templates/users/user_bulk_update.html:24
+#: users/templates/users/user_list.html:44
+#: users/templates/users/user_password_update.html:59
+#: users/templates/users/user_profile_update.html:64
+#: users/templates/users/user_pubkey_update.html:77
+msgid "Submit"
+msgstr "提交"
+
 #: assets/templates/assets/admin_user_assets.html:18
 #: assets/templates/assets/admin_user_detail.html:18
 #: assets/templates/assets/domain_detail.html:18
@@ -799,10 +706,19 @@ msgstr "资产列表"
 msgid "Asset list of "
 msgstr "资产列表"
 
+#: assets/templates/assets/admin_user_assets.html:54
+#: assets/templates/assets/admin_user_list.html:26
+#: assets/templates/assets/asset_list.html:90
+#: assets/templates/assets/system_user_asset.html:52
+#: assets/templates/assets/system_user_list.html:30
+#: users/templates/users/user_group_granted_asset.html:47
+msgid "Reachable"
+msgstr "可连接"
+
 #: assets/templates/assets/admin_user_assets.html:66
 #: assets/templates/assets/system_user_asset.html:64
 #: assets/templates/assets/system_user_detail.html:112
-#: perms/templates/perms/asset_permission_detail.html:110
+#: perms/templates/perms/asset_permission_detail.html:114
 msgid "Quick update"
 msgstr "快速更新"
 
@@ -818,15 +734,67 @@ msgstr "测试可连接性"
 msgid "Test"
 msgstr "测试"
 
+#: assets/templates/assets/admin_user_detail.html:24
+#: assets/templates/assets/admin_user_list.html:85
+#: assets/templates/assets/asset_detail.html:24
+#: assets/templates/assets/asset_list.html:170
+#: assets/templates/assets/domain_detail.html:24
+#: assets/templates/assets/domain_detail.html:103
+#: assets/templates/assets/domain_gateway_list.html:90
+#: assets/templates/assets/domain_list.html:42
+#: assets/templates/assets/label_list.html:38
+#: assets/templates/assets/system_user_detail.html:26
+#: assets/templates/assets/system_user_list.html:88
+#: perms/templates/perms/asset_permission_detail.html:30
+#: perms/templates/perms/asset_permission_list.html:191
+#: terminal/templates/terminal/terminal_detail.html:16
+#: terminal/templates/terminal/terminal_list.html:71
+#: users/templates/users/user_detail.html:25
+#: users/templates/users/user_group_detail.html:28
+#: users/templates/users/user_group_list.html:43
+#: users/templates/users/user_list.html:76
+#: users/templates/users/user_profile.html:135
+#: users/templates/users/user_profile.html:143
+msgid "Update"
+msgstr "æ›´æ–°"
+
+#: assets/templates/assets/admin_user_detail.html:28
+#: assets/templates/assets/admin_user_list.html:86
+#: assets/templates/assets/asset_detail.html:28
+#: assets/templates/assets/asset_list.html:171
+#: assets/templates/assets/domain_detail.html:28
+#: assets/templates/assets/domain_detail.html:104
+#: assets/templates/assets/domain_gateway_list.html:91
+#: assets/templates/assets/domain_list.html:43
+#: assets/templates/assets/label_list.html:39
+#: assets/templates/assets/system_user_detail.html:30
+#: assets/templates/assets/system_user_list.html:89
+#: ops/templates/ops/task_list.html:72
+#: perms/templates/perms/asset_permission_detail.html:34
+#: perms/templates/perms/asset_permission_list.html:192
+#: terminal/templates/terminal/terminal_list.html:73
+#: users/templates/users/user_detail.html:30
+#: users/templates/users/user_group_detail.html:32
+#: users/templates/users/user_group_list.html:45
+#: users/templates/users/user_list.html:80
+#: users/templates/users/user_list.html:84
+msgid "Delete"
+msgstr "删除"
+
 #: assets/templates/assets/admin_user_detail.html:83
 msgid "Replace node assets admin user with this"
 msgstr "替换资产的管理员"
 
+#: assets/templates/assets/admin_user_detail.html:91
+#: perms/templates/perms/asset_permission_asset.html:116
+msgid "Select nodes"
+msgstr "选择节点"
+
 #: assets/templates/assets/admin_user_detail.html:100
 #: assets/templates/assets/asset_detail.html:200
 #: assets/templates/assets/asset_list.html:600
 #: assets/templates/assets/system_user_detail.html:183
-#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:16
+#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:22
 #: terminal/templates/terminal/session_detail.html:108
 #: users/templates/users/user_detail.html:339
 #: users/templates/users/user_detail.html:364
@@ -855,20 +823,23 @@ msgstr "不可达"
 msgid "Ratio"
 msgstr "比例"
 
-#: assets/templates/assets/asset_create.html:29
-#: assets/templates/assets/asset_update.html:34 perms/models.py:74
-#: perms/templates/perms/asset_permission_create_update.html:40
-#: perms/templates/perms/asset_permission_list.html:67
-msgid "Node"
-msgstr "节点"
-
-#: assets/templates/assets/asset_create.html:35
-#: assets/templates/assets/asset_list.html:75
-#: assets/templates/assets/asset_update.html:40
-msgid "Label"
-msgstr "标签"
+#: assets/templates/assets/admin_user_list.html:30
+#: assets/templates/assets/asset_list.html:91
+#: assets/templates/assets/domain_gateway_list.html:62
+#: assets/templates/assets/domain_list.html:18
+#: assets/templates/assets/label_list.html:17
+#: assets/templates/assets/system_user_list.html:34
+#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
+#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
+#: perms/templates/perms/asset_permission_list.html:60
+#: terminal/templates/terminal/session_list.html:80
+#: terminal/templates/terminal/terminal_list.html:36
+#: users/templates/users/user_group_list.html:15
+#: users/templates/users/user_list.html:28
+msgid "Action"
+msgstr "动作"
 
-#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:197
+#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:198
 msgid "Asset detail"
 msgstr "资产详情"
 
@@ -893,6 +864,23 @@ msgstr "创建日期"
 msgid "Quick modify"
 msgstr "快速修改"
 
+#: assets/templates/assets/asset_detail.html:143
+#: assets/templates/assets/asset_list.html:89
+#: assets/templates/assets/user_asset_list.html:47 perms/models.py:25
+#: perms/models.py:70
+#: perms/templates/perms/asset_permission_create_update.html:47
+#: perms/templates/perms/asset_permission_detail.html:120
+#: perms/templates/perms/asset_permission_list.html:59
+#: terminal/templates/terminal/terminal_list.html:34
+#: users/templates/users/_select_user_modal.html:18
+#: users/templates/users/user_detail.html:128
+#: users/templates/users/user_granted_asset.html:46
+#: users/templates/users/user_group_granted_asset.html:46
+#: users/templates/users/user_list.html:27
+#: users/templates/users/user_profile.html:63
+msgid "Active"
+msgstr "激活中"
+
 #: assets/templates/assets/asset_detail.html:160
 msgid "Refresh hardware"
 msgstr "更新硬件信息"
@@ -906,8 +894,7 @@ msgstr "刷新"
 msgid "Update successfully!"
 msgstr "更新成功"
 
-#: assets/templates/assets/asset_list.html:63
-#: assets/templates/assets/asset_list.html:120 assets/views/asset.py:96
+#: assets/templates/assets/asset_list.html:63 assets/views/asset.py:97
 msgid "Create asset"
 msgstr "创建资产"
 
@@ -921,35 +908,63 @@ msgstr "导入"
 msgid "Export"
 msgstr "导出"
 
+#: assets/templates/assets/asset_list.html:88
+msgid "Hardware"
+msgstr "硬件"
+
+#: assets/templates/assets/asset_list.html:100
+#: users/templates/users/user_list.html:37
+msgid "Delete selected"
+msgstr "批量删除"
+
+#: assets/templates/assets/asset_list.html:101
+#: users/templates/users/user_list.html:38
+msgid "Update selected"
+msgstr "批量更新"
+
 #: assets/templates/assets/asset_list.html:102
 msgid "Remove from this node"
 msgstr "从节点移除"
 
+#: assets/templates/assets/asset_list.html:103
+#: users/templates/users/user_list.html:39
+msgid "Deactive selected"
+msgstr "禁用所选"
+
+#: assets/templates/assets/asset_list.html:104
+#: users/templates/users/user_list.html:40
+msgid "Active selected"
+msgstr "激活所选"
+
 #: assets/templates/assets/asset_list.html:121
-msgid "Add asset"
-msgstr "添加资产到节点"
+msgid "Add node"
+msgstr "新建节点"
 
 #: assets/templates/assets/asset_list.html:122
-msgid "Refresh node hardware info"
-msgstr "更新节点资产硬件信息"
+msgid "Rename node"
+msgstr "重命名节点"
 
 #: assets/templates/assets/asset_list.html:123
-msgid "Test node connective"
-msgstr "测试节点资产可连接性"
+msgid "Delete node"
+msgstr "删除节点"
 
 #: assets/templates/assets/asset_list.html:125
-msgid "Add node"
-msgstr "新建节点"
+msgid "Add assets to node"
+msgstr "添加资产到节点"
 
 #: assets/templates/assets/asset_list.html:126
-msgid "Rename node"
-msgstr "重命名节点"
+msgid "Move assets to node"
+msgstr "移动资产到节点"
 
 #: assets/templates/assets/asset_list.html:128
-msgid "Delete node"
-msgstr "删除节点"
+msgid "Refresh node hardware info"
+msgstr "更新节点资产硬件信息"
 
-#: assets/templates/assets/asset_list.html:203
+#: assets/templates/assets/asset_list.html:129
+msgid "Test node connective"
+msgstr "测试节点资产可连接性"
+
+#: assets/templates/assets/asset_list.html:204
 msgid "Create node failed"
 msgstr "创建节点失败"
 
@@ -957,6 +972,10 @@ msgstr "创建节点失败"
 msgid "Have child node, cancel"
 msgstr "存在子节点,不能删除"
 
+#: assets/templates/assets/asset_list.html:218
+msgid "Have assets, cancel"
+msgstr "存在资产,不能删除"
+
 #: assets/templates/assets/asset_list.html:595
 #: assets/templates/assets/system_user_list.html:133
 #: users/templates/users/user_detail.html:334
@@ -1088,10 +1107,6 @@ msgstr "删除系统用户"
 msgid "System Users Deleting failed."
 msgstr "系统用户删除失败"
 
-#: assets/templates/assets/user_asset_list.html:24
-msgid "Connective"
-msgstr "连接性"
-
 #: assets/views/admin_user.py:30
 msgid "Admin user list"
 msgstr "管理用户列表"
@@ -1104,23 +1119,19 @@ msgstr "更新管理用户"
 msgid "Admin user detail"
 msgstr "管理用户详情"
 
-#: assets/views/asset.py:50 templates/_nav.html:23
-msgid "Asset list"
-msgstr "资产列表"
-
-#: assets/views/asset.py:62 templates/_nav_user.html:4
+#: assets/views/asset.py:63 templates/_nav_user.html:4
 msgid "My assets"
 msgstr "我的资产"
 
-#: assets/views/asset.py:156
+#: assets/views/asset.py:157
 msgid "Bulk update asset"
 msgstr "批量更新资产"
 
-#: assets/views/asset.py:173
+#: assets/views/asset.py:174
 msgid "Update asset"
 msgstr "更新资产"
 
-#: assets/views/asset.py:300
+#: assets/views/asset.py:311
 msgid "already exists"
 msgstr "已经存在"
 
@@ -1182,18 +1193,33 @@ msgstr "远端地址"
 msgid "Operate"
 msgstr "操作"
 
-#: audits/models.py:14 audits/templates/audits/ftp_log_list.html:76
+#: audits/models.py:14 audits/templates/audits/ftp_log_list.html:56
+#: audits/templates/audits/ftp_log_list.html:76
 msgid "Filename"
 msgstr "文件名"
 
-#: audits/templates/audits/ftp_log_list.html:77
+#: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
+#: ops/templates/ops/task_list.html:39
+msgid "Success"
+msgstr "成功"
+
+#: audits/templates/audits/ftp_log_list.html:78
 #: ops/templates/ops/adhoc_history.html:52
 #: ops/templates/ops/adhoc_history_detail.html:61
-#: ops/templates/ops/task_history.html:58 terminal/models.py:132
+#: ops/templates/ops/task_history.html:58 perms/models.py:26
+#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:132
 #: terminal/templates/terminal/session_list.html:77
 msgid "Date start"
 msgstr "开始日期"
 
+#: audits/views.py:50 templates/_nav.html:64
+msgid "Audits"
+msgstr "日志审计"
+
+#: audits/views.py:51 templates/_nav.html:67
+msgid "FTP log"
+msgstr "FTP日志"
+
 #: common/api.py:18
 msgid "Test mail sent to {}, please check"
 msgstr "邮件已经发送{}, 请检查"
@@ -1655,10 +1681,6 @@ msgstr "搜索"
 msgid "Versions"
 msgstr "版本"
 
-#: ops/templates/ops/task_list.html:39
-msgid "Success"
-msgstr "成功"
-
 #: ops/templates/ops/task_list.html:40
 #: users/templates/users/login_log_list.html:54
 msgid "Date"
@@ -1685,24 +1707,37 @@ msgstr "任务列表"
 msgid "Task run history"
 msgstr "执行历史"
 
-#: perms/forms.py:22 perms/models.py:16 perms/models.py:75
-#: perms/templates/perms/asset_permission_list.html:68 templates/_nav.html:14
-#: users/models/group.py:25 users/models/user.py:37
+#: perms/forms.py:18 users/forms.py:176 users/forms.py:181 users/forms.py:193
+#: users/forms.py:223
+msgid "Select users"
+msgstr "选择用户"
+
+#: perms/forms.py:34 perms/models.py:21 perms/models.py:68
+#: perms/templates/perms/asset_permission_list.html:55
+#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
+#: users/models/group.py:25 users/models/user.py:42
 #: users/templates/users/_select_user_modal.html:16
 #: users/templates/users/user_detail.html:179
 #: users/templates/users/user_list.html:26
 msgid "User group"
 msgstr "用户组"
 
-#: perms/models.py:21 perms/models.py:78
-#: perms/templates/perms/asset_permission_detail.html:86
-#: perms/templates/perms/asset_permission_list.html:71 users/models/user.py:49
-#: users/templates/users/user_detail.html:95
+#: perms/forms.py:56
+msgid "User or group at least one required"
+msgstr ""
+
+#: perms/forms.py:65
+msgid "Asset or group at least one required"
+msgstr ""
+
+#: perms/models.py:27 perms/models.py:71
+#: perms/templates/perms/asset_permission_detail.html:90
+#: users/models/user.py:54 users/templates/users/user_detail.html:95
 #: users/templates/users/user_profile.html:96
 msgid "Date expired"
 msgstr "失效日期"
 
-#: perms/models.py:88 templates/_nav.html:34
+#: perms/models.py:81 templates/_nav.html:34
 msgid "Asset permission"
 msgstr "资产授权"
 
@@ -1723,7 +1758,7 @@ msgid "Add asset to this permission"
 msgstr "添加资产"
 
 #: perms/templates/perms/asset_permission_asset.html:97
-#: perms/templates/perms/asset_permission_detail.html:153
+#: perms/templates/perms/asset_permission_detail.html:157
 #: perms/templates/perms/asset_permission_user.html:97
 #: perms/templates/perms/asset_permission_user.html:125
 #: users/templates/users/user_group_detail.html:95
@@ -1731,12 +1766,8 @@ msgid "Add"
 msgstr "添加"
 
 #: perms/templates/perms/asset_permission_asset.html:108
-msgid "Add asset group to this permission"
-msgstr "添加资产组"
-
-#: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:275
-msgid "Select asset groups"
-msgstr "选择资产组"
+msgid "Add node to this permission"
+msgstr "添加节点"
 
 #: perms/templates/perms/asset_permission_asset.html:125
 #: users/templates/users/user_detail.html:196
@@ -1756,18 +1787,18 @@ msgid "Asset count"
 msgstr "资产数量"
 
 #: perms/templates/perms/asset_permission_detail.html:78
-msgid "Asset group count"
-msgstr "资产组数量"
+msgid "Node count"
+msgstr "节点数量"
 
 #: perms/templates/perms/asset_permission_detail.html:82
 msgid "System user count"
 msgstr "系统用户数量"
 
-#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:278
+#: perms/templates/perms/asset_permission_detail.html:148
 msgid "Select system users"
 msgstr "选择系统用户"
 
-#: perms/templates/perms/asset_permission_list.html:58
+#: perms/templates/perms/asset_permission_list.html:46
 msgid "Create permission"
 msgstr "创建授权规则"
 
@@ -1792,22 +1823,31 @@ msgstr "添加用户组"
 msgid "Select user groups"
 msgstr "选择用户组"
 
-#: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:31
+#: perms/views.py:25 perms/views.py:55 perms/views.py:70 perms/views.py:85
+#: perms/views.py:120 perms/views.py:151 templates/_nav.html:31
 msgid "Perms"
 msgstr "权限管理"
 
-#: perms/views.py:24
+#: perms/views.py:26
 msgid "Asset permission list"
 msgstr "资产授权列表"
 
-#: perms/views.py:48
+#: perms/views.py:56
 msgid "Create asset permission"
 msgstr "创建权限规则"
 
-#: perms/views.py:68
+#: perms/views.py:71 perms/views.py:86
 msgid "Update asset permission"
 msgstr "更新资产授权"
 
+#: perms/views.py:121
+msgid "Asset permission user list"
+msgstr "资产授权用户列表"
+
+#: perms/views.py:152
+msgid "Asset permission asset list"
+msgstr "资产授权资产列表"
+
 #: templates/_header_bar.html:18
 msgid "Supports"
 msgstr "商业支持"
@@ -1816,13 +1856,13 @@ msgstr "商业支持"
 msgid "Docs"
 msgstr "文档"
 
-#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:94
+#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:93
 #: users/templates/users/_user.html:36
 #: users/templates/users/user_password_update.html:37
 #: users/templates/users/user_profile.html:17
 #: users/templates/users/user_profile_update.html:37
 #: users/templates/users/user_profile_update.html:57
-#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:317
+#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:318
 msgid "Profile"
 msgstr "个人信息"
 
@@ -1873,15 +1913,15 @@ msgstr ""
 "\"%(user_pubkey_update)s\"> 链接 </a> 更新\n"
 "        "
 
-#: templates/_modal.html:15
+#: templates/_modal.html:21
 msgid "Close"
 msgstr "关闭"
 
 #: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
 #: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
-#: users/views/login.py:209 users/views/login.py:258 users/views/user.py:60
-#: users/views/user.py:75 users/views/user.py:94 users/views/user.py:150
-#: users/views/user.py:305 users/views/user.py:352 users/views/user.py:374
+#: users/views/login.py:205 users/views/login.py:254 users/views/user.py:60
+#: users/views/user.py:75 users/views/user.py:95 users/views/user.py:151
+#: users/views/user.py:306 users/views/user.py:353 users/views/user.py:375
 msgid "Users"
 msgstr "用户管理"
 
@@ -1925,14 +1965,6 @@ msgstr "终端管理"
 msgid "Job Center"
 msgstr "作业中心"
 
-#: templates/_nav.html:64
-msgid "Audits"
-msgstr "日志审计"
-
-#: templates/_nav.html:67
-msgid "FTP log"
-msgstr "FTP日志"
-
 #: templates/captcha/image.html:3
 msgid "Play CAPTCHA as audio file"
 msgstr "语言播放验证码"
@@ -2199,7 +2231,7 @@ msgstr ""
 msgid "Invalid token or cache refreshed."
 msgstr ""
 
-#: users/forms.py:28 users/models/user.py:38
+#: users/forms.py:27 users/models/user.py:43
 #: users/templates/users/_select_user_modal.html:15
 #: users/templates/users/user_detail.html:87
 #: users/templates/users/user_list.html:25
@@ -2207,55 +2239,55 @@ msgstr ""
 msgid "Role"
 msgstr "角色"
 
-#: users/forms.py:30 users/forms.py:140
+#: users/forms.py:29 users/forms.py:139
 msgid "ssh public key"
 msgstr "ssh公钥"
 
-#: users/forms.py:31 users/forms.py:141
+#: users/forms.py:30 users/forms.py:140
 msgid "ssh-rsa AAAA..."
 msgstr ""
 
-#: users/forms.py:32
+#: users/forms.py:31
 msgid "Paste user id_rsa.pub here."
 msgstr "复制用户公钥到这里"
 
-#: users/forms.py:50 users/templates/users/user_detail.html:187
+#: users/forms.py:49 users/templates/users/user_detail.html:187
 msgid "Join user groups"
 msgstr "添加到用户组"
 
-#: users/forms.py:60 users/forms.py:155
+#: users/forms.py:59 users/forms.py:154
 msgid "Public key should not be the same as your old one."
 msgstr "不能和原来的密钥相同"
 
-#: users/forms.py:64 users/forms.py:159 users/serializers.py:42
+#: users/forms.py:63 users/forms.py:158 users/serializers.py:42
 msgid "Not a valid ssh public key"
 msgstr "ssh密钥不合法"
 
-#: users/forms.py:100
+#: users/forms.py:99
 msgid "Old password"
 msgstr "原来密码"
 
-#: users/forms.py:105
+#: users/forms.py:104
 msgid "New password"
 msgstr "新密码"
 
-#: users/forms.py:110
+#: users/forms.py:109
 msgid "Confirm password"
 msgstr "确认密码"
 
-#: users/forms.py:120
+#: users/forms.py:119
 msgid "Old password error"
 msgstr "原来密码错误"
 
-#: users/forms.py:128
+#: users/forms.py:127
 msgid "Password does not match"
 msgstr "密码不一致"
 
-#: users/forms.py:142
+#: users/forms.py:141
 msgid "Paste your id_rsa.pub here."
 msgstr "复制你的公钥到这里"
 
-#: users/forms.py:170 users/models/user.py:46
+#: users/forms.py:169 users/models/user.py:51
 #: users/templates/users/user_password_update.html:43
 #: users/templates/users/user_profile.html:71
 #: users/templates/users/user_profile_update.html:43
@@ -2263,10 +2295,6 @@ msgstr "复制你的公钥到这里"
 msgid "Public key"
 msgstr "ssh公钥"
 
-#: users/forms.py:177 users/forms.py:182 users/forms.py:194 users/forms.py:224
-msgid "Select users"
-msgstr "选择用户"
-
 #: users/models/authentication.py:36
 msgid "Private Token"
 msgstr "ssh密钥"
@@ -2291,7 +2319,7 @@ msgstr "Agent"
 msgid "Date login"
 msgstr "登录日期"
 
-#: users/models/user.py:29 users/models/user.py:262
+#: users/models/user.py:29 users/models/user.py:281
 msgid "Administrator"
 msgstr "管理员"
 
@@ -2299,24 +2327,36 @@ msgstr "管理员"
 msgid "Application"
 msgstr "应用程序"
 
-#: users/models/user.py:36 users/templates/users/user_detail.html:71
+#: users/models/user.py:34
+msgid "Disable"
+msgstr "禁用"
+
+#: users/models/user.py:35
+msgid "Enable"
+msgstr "启用"
+
+#: users/models/user.py:36
+msgid "Force enable"
+msgstr "强制启用"
+
+#: users/models/user.py:41 users/templates/users/user_detail.html:71
 #: users/templates/users/user_profile.html:59
 msgid "Email"
 msgstr "邮件"
 
-#: users/models/user.py:39
+#: users/models/user.py:44
 msgid "Avatar"
 msgstr "头像"
 
-#: users/models/user.py:40 users/templates/users/user_detail.html:82
+#: users/models/user.py:45 users/templates/users/user_detail.html:82
 msgid "Wechat"
 msgstr "微信"
 
-#: users/models/user.py:42
+#: users/models/user.py:47
 msgid "Enable OTP"
 msgstr "二次验证"
 
-#: users/models/user.py:265
+#: users/models/user.py:284
 msgid "Administrator is the super user of system"
 msgstr "Administrator是初始的超级管理员"
 
@@ -2416,11 +2456,6 @@ msgstr "重置密码"
 msgid "Password again"
 msgstr "再次输入密码"
 
-#: users/templates/users/reset_password.html:57
-#: users/templates/users/user_profile.html:20
-msgid "Setting"
-msgstr "设置"
-
 #: users/templates/users/user_create.html:4
 #: users/templates/users/user_list.html:16 users/views/user.py:75
 msgid "Create user"
@@ -2431,7 +2466,7 @@ msgid "Reset link will be generated and sent to the user. "
 msgstr "生成重置密码连接,通过邮件发送给用户"
 
 #: users/templates/users/user_detail.html:19
-#: users/templates/users/user_granted_asset.html:18 users/views/user.py:151
+#: users/templates/users/user_granted_asset.html:18 users/views/user.py:152
 msgid "User detail"
 msgstr "用户详情"
 
@@ -2550,8 +2585,8 @@ msgstr "用户删除失败"
 msgid "OTP"
 msgstr ""
 
-#: users/templates/users/user_profile.html:100 users/views/user.py:180
-#: users/views/user.py:234
+#: users/templates/users/user_profile.html:100 users/views/user.py:181
+#: users/views/user.py:235
 msgid "User groups"
 msgstr "用户组"
 
@@ -2587,7 +2622,7 @@ msgstr "更新密钥"
 msgid "Or reset by server"
 msgstr "或者重置并下载密钥"
 
-#: users/templates/users/user_update.html:4 users/views/user.py:94
+#: users/templates/users/user_update.html:4 users/views/user.py:95
 msgid "Update user"
 msgstr "更新用户"
 
@@ -2733,78 +2768,78 @@ msgstr "更新用户组"
 msgid "User group granted asset"
 msgstr "用户组授权资产"
 
-#: users/views/login.py:57
+#: users/views/login.py:55
 msgid "Please enable cookies and try again."
 msgstr "设置你的浏览器支持cookie"
 
-#: users/views/login.py:99
+#: users/views/login.py:97
 msgid "Logout success"
 msgstr "退出登录成功"
 
-#: users/views/login.py:100
+#: users/views/login.py:98
 msgid "Logout success, return login page"
 msgstr "退出登录成功,返回到登录页面"
 
-#: users/views/login.py:116
+#: users/views/login.py:114
 msgid "Email address invalid, please input again"
 msgstr "邮箱地址错误,重新输入"
 
-#: users/views/login.py:129
+#: users/views/login.py:127
 msgid "Send reset password message"
 msgstr "发送重置密码邮件"
 
-#: users/views/login.py:130
+#: users/views/login.py:128
 msgid "Send reset password mail success, login your mail box and follow it "
 msgstr ""
 "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
 
-#: users/views/login.py:144
+#: users/views/login.py:142
 msgid "Reset password success"
 msgstr "重置密码成功"
 
-#: users/views/login.py:145
+#: users/views/login.py:143
 msgid "Reset password success, return to login page"
 msgstr "重置密码成功,返回到登录页面"
 
-#: users/views/login.py:162 users/views/login.py:175
+#: users/views/login.py:160 users/views/login.py:173
 msgid "Token invalid or expired"
 msgstr "Token错误或失效"
 
-#: users/views/login.py:171
+#: users/views/login.py:169
 msgid "Password not same"
 msgstr "密码不一致"
 
-#: users/views/login.py:209
+#: users/views/login.py:205
 msgid "First login"
 msgstr "首次登陆"
 
-#: users/views/login.py:259
+#: users/views/login.py:255
 msgid "Login log list"
 msgstr "登录日志"
 
-#: users/views/user.py:104
+#: users/views/user.py:105
 msgid "Bulk update user success"
 msgstr "批量更新用户成功"
 
-#: users/views/user.py:209
+#: users/views/user.py:210
 msgid "Invalid file."
 msgstr "文件不合法"
 
-#: users/views/user.py:306
+#: users/views/user.py:307
 msgid "User granted assets"
 msgstr "用户授权资产"
 
-#: users/views/user.py:335
+#: users/views/user.py:336
 msgid "Profile setting"
 msgstr "个人信息设置"
 
-#: users/views/user.py:353
+#: users/views/user.py:354
 msgid "Password update"
 msgstr "密码更新"
 
-#: users/views/user.py:375
+#: users/views/user.py:376
 msgid "Public key update"
 msgstr "密钥更新"
 
-#~ msgid "Task has been send, seen left asset status"
-#~ msgstr "任务已下发,查看左侧资产状态"
+#~ msgid "Add asset"
+#~ msgstr "添加资产到节点"
diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py
index ced4797d5ef07a79c20b64d7435affb68731ea6a..8300ebe068aa9d3bc77666aac0a44b763bf411c7 100644
--- a/apps/jumpserver/urls.py
+++ b/apps/jumpserver/urls.py
@@ -36,9 +36,10 @@ urlpatterns = [
     url(r'^captcha/', include('captcha.urls')),
 ]
 
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
+            + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+
 if settings.DEBUG:
     urlpatterns += [
         url(r'^docs/', schema_view, name="docs"),
-    ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \
-      + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
-
+    ]
diff --git a/apps/perms/api.py b/apps/perms/api.py
index 1303e4128c1acafbef0a877ed9486a838027667e..be69d615842e713e6411645d13d3ae946ae7f48a 100644
--- a/apps/perms/api.py
+++ b/apps/perms/api.py
@@ -3,7 +3,7 @@
 
 from django.shortcuts import get_object_or_404
 from rest_framework.views import APIView, Response
-from rest_framework.generics import ListAPIView, get_object_or_404
+from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView
 from rest_framework import viewsets
 
 from common.utils import set_or_append_attr_bulk
@@ -98,6 +98,11 @@ class UserGrantedNodesApi(ListAPIView):
         nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
         return nodes.keys()
 
+    def get_permissions(self):
+        if self.kwargs.get('pk') is None:
+            self.permission_classes = (IsValidUser,)
+        return super().get_permissions()
+
 
 class UserGrantedNodesWithAssetsApi(ListAPIView):
     permission_classes = (IsSuperUserOrAppUser,)
@@ -246,3 +251,77 @@ class ValidateUserAssetPermissionView(APIView):
             return Response({'msg': True}, status=200)
         else:
             return Response({'msg': False}, status=403)
+
+
+class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
+    """
+    将用户从授权中移除,Detail页面会调用
+    """
+    permission_classes = (IsSuperUser,)
+    serializer_class = serializers.AssetPermissionUpdateUserSerializer
+    queryset = AssetPermission.objects.all()
+
+    def update(self, request, *args, **kwargs):
+        perm = self.get_object()
+        serializer = self.serializer_class(data=request.data)
+        if serializer.is_valid():
+            users = serializer.validated_data.get('users')
+            if users:
+                perm.users.remove(*tuple(users))
+            return Response({"msg": "ok"})
+        else:
+            return Response({"error": serializer.errors})
+
+
+class AssetPermissionAddUserApi(RetrieveUpdateAPIView):
+    permission_classes = (IsSuperUser,)
+    serializer_class = serializers.AssetPermissionUpdateUserSerializer
+    queryset = AssetPermission.objects.all()
+
+    def update(self, request, *args, **kwargs):
+        perm = self.get_object()
+        serializer = self.serializer_class(data=request.data)
+        if serializer.is_valid():
+            users = serializer.validated_data.get('users')
+            if users:
+                perm.users.add(*tuple(users))
+            return Response({"msg": "ok"})
+        else:
+            return Response({"error": serializer.errors})
+
+
+class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView):
+    """
+    将用户从授权中移除,Detail页面会调用
+    """
+    permission_classes = (IsSuperUser,)
+    serializer_class = serializers.AssetPermissionUpdateAssetSerializer
+    queryset = AssetPermission.objects.all()
+
+    def update(self, request, *args, **kwargs):
+        perm = self.get_object()
+        serializer = self.serializer_class(data=request.data)
+        if serializer.is_valid():
+            assets = serializer.validated_data.get('assets')
+            if assets:
+                perm.assets.remove(*tuple(assets))
+            return Response({"msg": "ok"})
+        else:
+            return Response({"error": serializer.errors})
+
+
+class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
+    permission_classes = (IsSuperUser,)
+    serializer_class = serializers.AssetPermissionUpdateAssetSerializer
+    queryset = AssetPermission.objects.all()
+
+    def update(self, request, *args, **kwargs):
+        perm = self.get_object()
+        serializer = self.serializer_class(data=request.data)
+        if serializer.is_valid():
+            assets = serializer.validated_data.get('assets')
+            if assets:
+                perm.assets.add(*tuple(assets))
+            return Response({"msg": "ok"})
+        else:
+            return Response({"error": serializer.errors})
diff --git a/apps/perms/forms.py b/apps/perms/forms.py
index 060812d4a19816b02e2f64941bdb91b8fbac1b38..c418160dd20697164f908db6855d45e346accb7f 100644
--- a/apps/perms/forms.py
+++ b/apps/perms/forms.py
@@ -4,10 +4,23 @@ from __future__ import absolute_import, unicode_literals
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 
+from .hands import User
 from .models import AssetPermission
 
 
 class AssetPermissionForm(forms.ModelForm):
+    users = forms.ModelMultipleChoiceField(
+        queryset=User.objects.exclude(role=User.ROLE_APP),
+        label=_("User"),
+        widget=forms.SelectMultiple(
+            attrs={
+                'class': 'select2',
+                'data-placeholder': _('Select users')
+            }
+        ),
+        required=False,
+    )
+
     class Meta:
         model = AssetPermission
         exclude = (
diff --git a/apps/perms/models.py b/apps/perms/models.py
index 6609cd8e22f722d24e9faabe09c34903a6cef532..954cbe5f62865f8394a4bbeb9c31e0f12e1592a7 100644
--- a/apps/perms/models.py
+++ b/apps/perms/models.py
@@ -4,7 +4,7 @@ from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from django.utils import timezone
 
-from common.utils import date_expired_default
+from common.utils import date_expired_default, set_or_append_attr_bulk
 
 
 class ValidManager(models.Manager):
@@ -45,6 +45,22 @@ class AssetPermission(models.Model):
             return True
         return False
 
+    def get_all_users(self):
+        users = set(self.users.all())
+        for group in self.user_groups.all():
+            _users = group.users.all()
+            set_or_append_attr_bulk(_users, 'inherit', group.name)
+            users.update(set(_users))
+        return users
+
+    def get_all_assets(self):
+        assets = set(self.assets.all())
+        for node in self.nodes.all():
+            _assets = node.get_all_assets()
+            set_or_append_attr_bulk(_assets, 'inherit', node.value)
+            assets.update(set(_assets))
+        return assets
+
 
 class NodePermission(models.Model):
     id = models.UUIDField(default=uuid.uuid4, primary_key=True)
diff --git a/apps/perms/templates/perms/asset_permission_asset.html b/apps/perms/templates/perms/asset_permission_asset.html
index 12369574da95283737b57d21d77307eb0dc934ff..364d7e60fe6cb934ebbe5f73f24677d00d7d154d 100644
--- a/apps/perms/templates/perms/asset_permission_asset.html
+++ b/apps/perms/templates/perms/asset_permission_asset.html
@@ -57,12 +57,12 @@
                                             </tr>
                                         </thead>
                                         <tbody>
-                                            {% for asset in page_obj %}
+                                            {% for asset in object_list %}
                                             <tr>
                                                 <td>{{ asset.hostname }}</td>
                                                 <td>{{ asset.ip }}</td>
                                                 <td>
-                                                    <button title="{{ asset.inherit_from_asset_groups }}" data-gid="{{ asset.id }}" class="btn btn-danger btn-xs btn-remove-asset {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
+                                                    <button title="{{ asset.inherit }}" data-gid="{{ asset.id }}" class="btn btn-danger btn-xs btn-remove-asset {% if asset.inherit %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
                                                 </td>
                                             </tr>
                                             {% endfor %}
@@ -85,9 +85,9 @@
                                         <form>
                                             <tr class="no-borders-tr">
                                                 <td colspan="2">
-                                                    <select data-placeholder="{% trans 'Select assets' %}" class="select2 asset" style="width: 100%" multiple="" tabindex="4">
+                                                    <select data-placeholder="{% trans 'Select assets' %}" class="select2" id="asset_select2" style="width: 100%" multiple="" tabindex="4">
                                                         {% for asset in assets_remain %}
-                                                            <option value="{{ asset.id }}">{{ asset.hostname }}</option>
+                                                            <option value="{{ asset.id }}">{{ asset }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
@@ -105,7 +105,7 @@
 
                             <div class="panel panel-info">
                                 <div class="panel-heading">
-                                    <i class="fa fa-info-circle"></i> {% trans 'Add asset group to this permission' %}
+                                    <i class="fa fa-info-circle"></i> {% trans 'Add node to this permission' %}
                                 </div>
                                 <div class="panel-body">
                                     <table class="table group_edit">
@@ -113,25 +113,25 @@
                                         <form>
                                             <tr>
                                                 <td colspan="2" class="no-borders">
-                                                    <select data-placeholder="{% trans 'Select asset groups' %}" class="select2 group" style="width: 100%" multiple="" tabindex="4">
-                                                        {% for asset_group in asset_groups_remain %}
-                                                        <option value="{{ asset_group.id }}" id="opt_{{ asset_group.id }}">{{ asset_group.name }}</option>
+                                                    <select data-placeholder="{% trans 'Select nodes' %}" class="select2" id="node_select2" style="width: 100%" multiple="" tabindex="4">
+                                                        {% for node in nodes_remain %}
+                                                        <option value="{{ node.id }}" id="opt_{{ node.id }}">{{ node }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
                                             </tr>
                                             <tr>
                                                 <td colspan="2" class="no-borders">
-                                                    <button type="button" class="btn btn-info btn-sm" id="btn-add-group">{% trans 'Join' %}</button>
+                                                    <button type="button" class="btn btn-info btn-sm" id="btn-add-node">{% trans 'Join' %}</button>
                                                 </td>
                                             </tr>
                                         </form>
 
-                                        {% for asset_group in asset_groups %}
+                                        {% for node in asset_permission.nodes.all %}
                                         <tr>
-                                          <td ><b class="bdg_user_group" data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td>
+                                          <td ><b class="bdg_group" data-gid={{ node.id }}>{{ node }}</b></td>
                                           <td>
-                                              <button class="btn btn-danger btn-xs btn-remove-group" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
+                                              <button class="btn btn-danger btn-xs btn-remove-node" type="button" data-gid="{{ node.id }}" style="float: right;"><i class="fa fa-minus"></i></button>
                                           </td>
                                         </tr>
                                         {% endfor %}
@@ -179,49 +179,30 @@ function removeAssets(assets) {
     });
 }
 
-function updateGroup(groups) {
+function updateNodes(nodes, success) {
     var the_url = "{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}";
     var body = {
-        asset_groups: groups
+        nodes: nodes
     };
     APIUpdateAttr({
         url: the_url,
-        body: JSON.stringify(body)
+        body: JSON.stringify(body),
+        success: success
     });
 }
 
-jumpserver.assets_selected = {};
-jumpserver.nodes_selected = {};
 
 $(document).ready(function () {
-     $('.select2.asset').select2()
-        .on('select2:select', function(evt) {
-             var data = evt.params.data;
-             jumpserver.assets_selected[data.id] = data.text;
-        })
-        .on('select2:unselect', function(evt) {
-            var data = evt.params.data;
-            delete jumpserver.assets_selected[data.id]
-        });
-    $('.select2.group').select2()
-        .on('select2:select', function(evt) {
-             var data = evt.params.data;
-             jumpserver.nodes_selected[data.id] = data.text;
-        })
-        .on('select2:unselect', function(evt) {
-            var data = evt.params.data;
-            delete jumpserver.nodes_selected[data.id]
-        })
+     $('.select2').select2();
 })
 .on('click', '.btn-add-assets', function () {
-    if (Object.keys(jumpserver.assets_selected).length === 0) {
+    var assets_selected = $("#asset_select2 option:selected").map(function () {
+        return $(this).attr('value');
+    }).get();
+    if (assets_selected.length === 0) {
 		return false;
 	}
-	var assets = [];
-    $.map(jumpserver.assets_selected, function(value, index) {
-        assets.push(index);
-    });
-    addAssets(assets);
+    addAssets(assets_selected);
 })
 .on('click', '.btn-remove-asset', function () {
     var asset_id = $(this).data("gid");
@@ -231,38 +212,44 @@ $(document).ready(function () {
     var assets = [asset_id];
     removeAssets(assets)
 })
-.on('click', '#btn-add-group', function () {
-    if (Object.keys(jumpserver.nodes_selected).length === 0) {
+.on('click', '#btn-add-node', function () {
+    var nodes_selected = {};
+    $("#node_select2 option:selected").each(function (i, data) {
+        nodes_selected[$(data).attr('value')] = $(data).text();
+    });
+    if (Object.keys(nodes_selected).length === 0) {
 		return false;
 	}
-
-    var groups = $('.bdg_group').map(function() {
+    var nodes_origin = $('.bdg_group').map(function() {
         return $(this).data('gid');
     }).get();
 
-    $.map(jumpserver.nodes_selected, function(group_name, index) {
-        groups.push(index);
-        $('#opt_' + index).remove();
-        $('.group_edit tbody').append(
-           '<tr>' +
-           '<td><b class="bdg_group" data-gid="' + index + '">' + group_name + '</b></td>' +
-           '<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>' +
-           '</tr>'
-        )
-    });
-
-    updateGroup(groups);
+    var nodes = nodes_origin.concat(Object.keys(nodes_selected));
+    var success = function () {
+        $.map(nodes_selected, function(name, id) {
+            $('#opt_' + id).remove();
+            $('.group_edit tbody').append(
+               '<tr>' +
+               '<td><b class="bdg_group" data-gid="' + id + '">' + name + '</b></td>' +
+               '<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>' +
+               '</tr>'
+            )
+        });
+    };
+    updateNodes(nodes, success);
 })
-.on('click', '.btn-remove-group', function () {
+.on('click', '.btn-remove-node', function () {
     var $this = $(this);
     var $tr = $this.closest('tr');
-    var groups = $('.bdg_group').map(function() {
+    var nodes = $('.bdg_group').map(function() {
         if ($(this).data('gid') !== $this.data('gid')){
             return $(this).data('gid');
         }
     }).get();
-    updateGroup(groups);
-    $tr.remove()
+    var success = function () {
+        $tr.remove()
+    };
+    updateNodes(nodes, success);
 })
 </script>
 {% endblock %}
diff --git a/apps/perms/templates/perms/asset_permission_create_update.html b/apps/perms/templates/perms/asset_permission_create_update.html
index 19704485672875ecaa8718c505a4a7aa8d35ee6d..551aab142e829c5bc25c8dd4f14193f0c5ebd053 100644
--- a/apps/perms/templates/perms/asset_permission_create_update.html
+++ b/apps/perms/templates/perms/asset_permission_create_update.html
@@ -76,20 +76,37 @@
             </div>
         </div>
     </div>
+    {% include 'assets/_asset_list_modal.html' %}
 {% endblock %}
 {% block custom_foot_js %}
-    <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
-    <script>
-        $(document).ready(function () {
-            $('.select2').select2();
-            $('#datepicker').datepicker({
-                format: "yyyy-mm-dd",
-                todayBtn: "linked",
-                keyboardNavigation: false,
-                forceParse: false,
-                calendarWeeks: true,
-                autoclose: true
-            });
-        })
-    </script>
+<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
+<script>
+$(document).ready(function () {
+    $('.select2').select2({
+        closeOnSelect: false
+    });
+    $('#datepicker').datepicker({
+        format: "yyyy-mm-dd",
+        todayBtn: "linked",
+        keyboardNavigation: false,
+        forceParse: false,
+        calendarWeeks: true,
+        autoclose: true
+    });
+    $("#id_assets").parent().find(".select2-selection").on('click', function (e) {
+        e.preventDefault();
+        $("#asset_list_modal").modal();
+    })
+})
+.on('click', '#btn_asset_modal_confirm', function () {
+    var assets = asset_table2.selected;
+    $('.select2 option:selected').each(function (i, data) {
+        assets.push($(data).attr('value'))
+    });
+    $.each(assets, function (id, data) {
+        $('.select2').val(assets).trigger('change');
+    });
+    $("#asset_list_modal").modal('hide');
+})
+</script>
 {% endblock %}
\ No newline at end of file
diff --git a/apps/perms/templates/perms/asset_permission_detail.html b/apps/perms/templates/perms/asset_permission_detail.html
index 5540ca515243c7878613a16edb2696cdae3d0fd4..3996cb274b8b328f7d8e582d9816d693ac91db49 100644
--- a/apps/perms/templates/perms/asset_permission_detail.html
+++ b/apps/perms/templates/perms/asset_permission_detail.html
@@ -15,19 +15,19 @@
                     <div class="panel-options">
                         <ul class="nav nav-tabs">
                             <li class="active">
-                                <a href="{% url 'perms:asset-permission-detail' pk=asset_permission.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
+                                <a href="{% url 'perms:asset-permission-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
                             </li>
                             <li>
-                                <a href="{% url 'perms:asset-permission-user-list' pk=asset_permission.id %}" class="text-center">
+                                <a href="{% url 'perms:asset-permission-user-list' pk=object.id %}" class="text-center">
                                 <i class="fa fa-bar-chart-o"></i> {% trans 'Users and user groups' %}
                                 </a>
                             </li>
                             <li>
-                                <a href="{% url 'perms:asset-permission-asset-list' pk=asset_permission.id  %}" class="text-center">
+                                <a href="{% url 'perms:asset-permission-asset-list' pk=object.id %}" class="text-center">
                                 <i class="fa fa-bar-chart-o"></i> {% trans 'Assets and asset groups' %}</a>
                             </li>
                             <li class="pull-right">
-                                <a class="btn btn-outline btn-default" href="{% url 'perms:asset-permission-update' pk=asset_permission.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
+                                <a class="btn btn-outline btn-default" href="{% url 'perms:asset-permission-update' pk=object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
                             </li>
                             <li class="pull-right">
                                 <a class="btn btn-outline btn-danger btn-delete-perm">
@@ -40,7 +40,7 @@
                         <div class="col-sm-7" style="padding-left: 0;">
                             <div class="ibox float-e-margins">
                                 <div class="ibox-title">
-                                    <span class="label"><b>{{ asset_permission.name }}</b></span>
+                                    <span class="label"><b>{{ object.name }}</b></span>
                                     <div class="ibox-tools">
                                         <a class="collapse-link">
                                             <i class="fa fa-chevron-up"></i>
@@ -60,43 +60,47 @@
                                         <tbody>
                                         <tr class="no-borders-tr">
                                             <td>{% trans 'Name' %}:</td>
-                                            <td><b>{{ asset_permission.name }}</b></td>
+                                            <td><b>{{ object.name }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'User count' %}:</td>
-                                            <td><b>{{ asset_permission.users.count }}</b></td>
+                                            <td><b>{{ object.users.count }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'User group count' %}:</td>
-                                            <td><b>{{ asset_permission.users.count }}</b></td>
+                                            <td><b>{{ object.users.count }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'Asset count' %}:</td>
-                                            <td><b>{{ asset_permission.assets.count }}</b></td>
+                                            <td><b>{{ object.assets.count }}</b></td>
                                         </tr>
                                         <tr>
-                                            <td>{% trans 'Asset group count' %}:</td>
-                                            <td><b>{{ asset_permission.asset_groups.count }}</b></td>
+                                            <td>{% trans 'Node count' %}:</td>
+                                            <td><b>{{ object.nodes.count }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'System user count' %}:</td>
-                                            <td><b>{{ asset_permission.system_users.count }}</b></td>
+                                            <td><b>{{ object.system_users.count }}</b></td>
+                                        </tr>
+                                        <tr>
+                                            <td>{% trans 'Date start' %}:</td>
+                                            <td><b>{{ object.date_start }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'Date expired' %}:</td>
-                                            <td><b>{{ asset_permission.date_expired }}</b></td>
+                                            <td><b>{{ object.date_expired }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'Date created' %}:</td>
-                                            <td><b>{{ asset_permission.date_created }}</b></td>
+                                            <td><b>{{ object.date_created }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'Created by' %}:</td>
-                                            <td><b>{{ asset_permission.created_by  }}</b></td>
+                                            <td><b>{{ object.created_by  }}</b></td>
                                         </tr>
                                         <tr>
                                             <td>{% trans 'Comment' %}:</td>
-                                            <td><b>{{ asset_permission.comment }}</b></td>
+                                            <td><b>{{ object.comment }}</b></td>
                                         </tr>
                                         </tbody>
                                     </table>
@@ -117,7 +121,7 @@
                                             <td><span style="float: right">
                                                 <div class="switch">
                                                     <div class="onoffswitch">
-                                                        <input type="checkbox" {% if asset_permission.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
+                                                        <input type="checkbox" {% if object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
                                                         <label class="onoffswitch-label" for="is_active">
                                                             <span class="onoffswitch-inner"></span>
                                                             <span class="onoffswitch-switch"></span>
@@ -143,7 +147,7 @@
                                                 <td colspan="2">
                                                     <select data-placeholder="{% trans 'Select system users' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
                                                         {% for system_user in system_users_remain %}
-                                                        <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option>
+                                                        <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
@@ -155,9 +159,9 @@
                                             </tr>
                                         </form>
 
-                                        {% for system_user in system_users %}
+                                        {% for system_user in object.system_users.all %}
                                         <tr {% if forloop.counter == 1 %} class="no-borders-tr" {% endif %} >
-                                          <td ><b class="bdg-system-user" data-uid={{ system_user.id }}>{{ system_user.name }}</b></td>
+                                          <td ><b class="bdg-system-user" data-uid={{ system_user.id }}>{{ system_user }}</b></td>
                                           <td>
                                               <button class="btn btn-danger btn-xs btn-remove-user" data-uid="{{ system_user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
                                           </td>
@@ -179,7 +183,7 @@
 jumpserver.system_users_selected = {};
 
 function updateSystemUser(system_users) {
-    var the_url = "{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}";
+    var the_url = "{% url 'api-perms:asset-permission-detail' pk=object.id %}";
     var body = {
         system_users: Object.assign([], system_users)
     };
@@ -203,7 +207,7 @@ $(document).ready(function () {
 .on('click', '.btn-delete-perm', function () {
     var $this = $(this);
     var name = "{{ asset_permission.name }}";
-    var uid = "{{ asset_permission.id }}";
+    var uid = "{{ object.id }}";
     var the_url = '{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
     var redirect_url = "{% url 'perms:asset-permission-list' %}";
     objectDelete($this, name, the_url, redirect_url);
@@ -238,7 +242,7 @@ $(document).ready(function () {
     updateSystemUser(system_users);
     $tr.remove()
 }).on('click', '#is_active', function () {
-    var the_url = '{% url "api-perms:asset-permission-detail" pk=asset_permission.id %}';
+    var the_url = '{% url "api-perms:asset-permission-detail" pk=object.id %}';
     var checked = $(this).prop('checked');
     var body = {
         'is_active': checked
diff --git a/apps/perms/templates/perms/asset_permission_user.html b/apps/perms/templates/perms/asset_permission_user.html
index bee5b0e35acb2c8037e2b2e9f725a57876fd9fc8..5d490bc280566302f7a848c4717fc0aa3d5eb118 100644
--- a/apps/perms/templates/perms/asset_permission_user.html
+++ b/apps/perms/templates/perms/asset_permission_user.html
@@ -57,12 +57,12 @@
                                             </tr>
                                         </thead>
                                         <tbody>
-                                            {% for user in page_obj %}
+                                            {% for user in object_list %}
                                             <tr>
                                                 <td>{{ user.name }}</td>
                                                 <td>{{ user.username }}</td>
                                                 <td>
-                                                    <button class="btn btn-danger btn-xs btn-remove-user {% if user.is_inherit_from_user_groups %} disabled {% endif %}" data-gid="{{ user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
+                                                    <button class="btn btn-danger btn-xs btn-remove-user {% if user.inherit %} disabled {% endif %}" data-gid="{{ user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
                                                 </td>
                                             </tr>
                                             {% endfor %}
@@ -87,7 +87,7 @@
                                                 <td colspan="2">
                                                     <select data-placeholder="{% trans 'Select user' %}" class="select2 user" style="width: 100%" multiple="" tabindex="4">
                                                         {% for user in users_remain %}
-                                                            <option value="{{ user.id }}">{{ user.name }}</option>
+                                                            <option value="{{ user.id }}">{{ user }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
@@ -115,7 +115,7 @@
                                                 <td colspan="2" class="no-borders">
                                                     <select data-placeholder="{% trans 'Select user groups' %}" class="select2 user-group" style="width: 100%" multiple="" tabindex="4">
                                                         {% for user_group in user_groups_remain %}
-                                                        <option value="{{ user_group.id }}" id="opt_{{ user_group.id }}">{{ user_group.name }}</option>
+                                                        <option value="{{ user_group.id }}" id="opt_{{ user_group.id }}">{{ user_group }}</option>
                                                         {% endfor %}
                                                     </select>
                                                 </td>
@@ -127,9 +127,9 @@
                                             </tr>
                                         </form>
 
-                                        {% for user_group in user_groups %}
+                                        {% for user_group in asset_permission.user_groups.all %}
                                         <tr>
-                                          <td ><b class="bdg_group" data-gid={{ user_group.id }}>{{ user_group.name }}</b></td>
+                                          <td ><b class="bdg_group" data-gid={{ user_group.id }}>{{ user_group }}</b></td>
                                           <td>
                                               <button class="btn btn-danger btn-xs btn-remove-group" type="button" data-gid="{{ user_group.id }}" style="float: right;"><i class="fa fa-minus"></i></button>
                                           </td>
diff --git a/apps/perms/urls/api_urls.py b/apps/perms/urls/api_urls.py
index d114e4f0b32b43336faf0a899ac3aaffbe3c4b80..f15450141563499b3bc297a09e3dc14ab4b739f6 100644
--- a/apps/perms/urls/api_urls.py
+++ b/apps/perms/urls/api_urls.py
@@ -11,20 +11,50 @@ router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'asset-permi
 
 urlpatterns = [
     # 查询某个用户授权的资产和资产组
-    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedAssetsApi.as_view(), name='user-assets'),
-    url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(), name='my-assets'),
-    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGrantedNodesApi.as_view(), name='user-nodes'),
-    url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(), name='my-nodes'),
-    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'),
-    url(r'^v1/user/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'),
-    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'),
-    url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='my-nodes-assets'),
+    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
+        api.UserGrantedAssetsApi.as_view(), name='user-assets'),
+    url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(),
+        name='my-assets'),
+    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
+        api.UserGrantedNodesApi.as_view(), name='user-nodes'),
+    url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(),
+        name='my-nodes'),
+    url(
+        r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
+        api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'),
+    url(r'^v1/user/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
+        api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'),
+    url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$',
+        api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'),
+    url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(),
+        name='my-nodes-assets'),
 
     # 查询某个用户组授权的资产和资产组
-    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
-    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'),
-    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGroupGrantedNodesWithAssetsApi.as_view(), name='user-group-nodes-assets'),
-    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedNodeAssetsApi.as_view(), name='user-group-node-assets'),
+    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
+        api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
+    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
+        api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'),
+    url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$',
+        api.UserGroupGrantedNodesWithAssetsApi.as_view(),
+        name='user-group-nodes-assets'),
+    url(
+        r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
+        api.UserGroupGrantedNodeAssetsApi.as_view(),
+        name='user-group-node-assets'),
+
+    # 用户和资产授权变更
+    url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/user/remove/$',
+        api.AssetPermissionRemoveUserApi.as_view(),
+        name='asset-permission-remove-user'),
+    url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/user/add/$',
+        api.AssetPermissionAddUserApi.as_view(),
+        name='asset-permission-add-user'),
+    url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/asset/remove/$',
+        api.AssetPermissionRemoveAssetApi.as_view(),
+        name='asset-permission-remove-asset'),
+    url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/asset/add/$',
+        api.AssetPermissionAddAssetApi.as_view(),
+        name='asset-permission-add-asset'),
 
     # 验证用户是否有某个资产和系统用户的权限
     url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'),
diff --git a/apps/perms/urls/views_urls.py b/apps/perms/urls/views_urls.py
index a1acc570c9c6a292de6494187fd692a794249406..5c3fa3b485c206edc5d3a289657126d303365788 100644
--- a/apps/perms/urls/views_urls.py
+++ b/apps/perms/urls/views_urls.py
@@ -11,8 +11,8 @@ urlpatterns = [
     url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'),
     url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'),
     url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'),
-    # url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'),
-    # url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'),
+    url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'),
+    url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'),
 ]
 
 
diff --git a/apps/perms/views.py b/apps/perms/views.py
index 2aa1ddd8b615a230bcf4be65a808088f998de2af..8babf519f03db30096b97ba4af24b04293f3c58b 100644
--- a/apps/perms/views.py
+++ b/apps/perms/views.py
@@ -4,12 +4,12 @@ from __future__ import unicode_literals, absolute_import
 
 from django.utils.translation import ugettext as _
 from django.views.generic import ListView, CreateView, UpdateView, DetailView
-from django.views.generic.edit import DeleteView
+from django.views.generic.edit import DeleteView, SingleObjectMixin
 from django.urls import reverse_lazy
 from django.conf import settings
 
-from common.utils import is_uuid
-from .hands import AdminUserRequiredMixin, Node, Asset
+from common.mixins import AdminUserRequiredMixin
+from .hands import Node, Asset, SystemUser, User, UserGroup
 from .models import AssetPermission
 from .forms import AssetPermissionForm
 
@@ -83,7 +83,11 @@ class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView):
     def get_context_data(self, **kwargs):
         context = {
             'app': _('Perms'),
-            'action': _('Update asset permission')
+            'action': _('Update asset permission'),
+            'system_users_remain': SystemUser.objects.exclude(
+                granted_by_permissions=self.object
+            ),
+
         }
         kwargs.update(context)
         return super().get_context_data(**kwargs)
@@ -95,3 +99,59 @@ class AssetPermissionDeleteView(AdminUserRequiredMixin, DeleteView):
     success_url = reverse_lazy('perms:asset-permission-list')
 
 
+class AssetPermissionUserView(AdminUserRequiredMixin,
+                              SingleObjectMixin,
+                              ListView):
+    template_name = 'perms/asset_permission_user.html'
+    context_object_name = 'asset_permission'
+    paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+    object = None
+
+    def get(self, request, *args, **kwargs):
+        self.object = self.get_object(queryset=AssetPermission.objects.all())
+        return super().get(request, *args, **kwargs)
+
+    def get_queryset(self):
+        queryset = self.object.get_all_users()
+        return queryset
+
+    def get_context_data(self, **kwargs):
+        context = {
+            'app': _('Perms'),
+            'action': _('Asset permission user list'),
+            'users_remain': User.objects.exclude(asset_permissions=self.object)
+                .exclude(role=User.ROLE_APP),
+            'user_groups_remain': UserGroup.objects.exclude(
+                asset_permissions=self.object
+            )
+        }
+        kwargs.update(context)
+        return super().get_context_data(**kwargs)
+
+
+class AssetPermissionAssetView(AdminUserRequiredMixin,
+                               SingleObjectMixin,
+                               ListView):
+    template_name = 'perms/asset_permission_asset.html'
+    context_object_name = 'asset_permission'
+    paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+    object = None
+
+    def get(self, request, *args, **kwargs):
+        self.object = self.get_object(queryset=AssetPermission.objects.all())
+        return super().get(request, *args, **kwargs)
+
+    def get_queryset(self):
+        queryset = self.object.get_all_assets()
+        return queryset
+
+    def get_context_data(self, **kwargs):
+        assets_granted = self.get_queryset()
+        context = {
+            'app': _('Perms'),
+            'action': _('Asset permission asset list'),
+            'assets_remain': Asset.objects.exclude(id__in=[a.id for a in assets_granted]),
+            'nodes_remain': Node.objects.exclude(granted_by_permissions=self.object),
+        }
+        kwargs.update(context)
+        return super().get_context_data(**kwargs)
\ No newline at end of file
diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js
index f2f8b8f55345b7542f7c93c53bc3725e722cb205..4614550854c12f6c36ed1dc12b83f8c3c3df95d3 100644
--- a/apps/static/js/jumpserver.js
+++ b/apps/static/js/jumpserver.js
@@ -307,7 +307,7 @@ jumpserver.initDataTable = function (options) {
                 last:       "»"
             }
         },
-        lengthMenu: [[15, 25, 50, -1], [15, 25, 50, "All"]]
+        lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
     });
     table.on('select', function(e, dt, type, indexes) {
         var $node = table[ type ]( indexes ).nodes().to$();
@@ -446,22 +446,56 @@ jumpserver.initServerSideDataTable = function (options) {
                 last:       "»"
             }
         },
-        lengthMenu: [[15, 25, 50], [15, 25, 50]]
+        lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]]
     });
+    table.selected = [];
     table.on('select', function(e, dt, type, indexes) {
         var $node = table[ type ]( indexes ).nodes().to$();
         $node.find('input.ipt_check').prop('checked', true);
-        jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true
+        jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true;
+        if (type === 'row') {
+            var rows = table.rows(indexes).data();
+            $.each(rows, function (id, row) {
+                if (row.id){
+                    table.selected.push(row.id)
+                }
+            })
+        }
     }).on('deselect', function(e, dt, type, indexes) {
         var $node = table[ type ]( indexes ).nodes().to$();
         $node.find('input.ipt_check').prop('checked', false);
-        jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false
+        jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false;
+        if (type === 'row') {
+            var rows = table.rows(indexes).data();
+            $.each(rows, function (id, row) {
+                if (row.id){
+                    var index = table.selected.indexOf(row.id);
+                    if (index > -1){
+                        table.selected.splice(index, 1)
+                    }
+                }
+            })
+        }
     }).
     on('draw', function(){
         $('#op').html(options.op_html || '');
         $('#uc').html(options.uc_html || '');
+        var table_data = [];
+        $.each(table.rows().data(), function (id, row) {
+            if (row.id) {
+                table_data.push(row.id)
+            }
+        });
+
+        $.each(table.selected, function (id, data) {
+            var index = table_data.indexOf(data);
+            if (index > -1){
+                table.rows(index).select()
+            }
+        });
     });
-    $('.ipt_check_all').on('click', function() {
+    var table_id = table.settings()[0].sTableId;
+    $('#' + table_id + ' .ipt_check_all').on('click', function() {
         if ($(this).prop("checked")) {
             $(this).closest('table').find('.ipt_check').prop('checked', true);
             table.rows({search:'applied', page:'current'}).select();
diff --git a/apps/templates/_footer.html b/apps/templates/_footer.html
index c9641c4fa3f6f0a3984e71ca242a31baf3191720..dbe60e1bc512a42948e347c641333206712c8ab5 100644
--- a/apps/templates/_footer.html
+++ b/apps/templates/_footer.html
@@ -1,6 +1,6 @@
 <div class="footer fixed">
     <div class="pull-right">
-        Version <strong>1.0.0-{% include '_build.html' %}</strong> GPLv2.
+        Version <strong>1.2.0-{% include '_build.html' %}</strong> GPLv2.
         <img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">
     </div>
     <div>
diff --git a/apps/templates/_modal.html b/apps/templates/_modal.html
index ad7f21ccc0b55352d9d3fcf1222e8cc4c0346595..e84586d0c05b81ed0067d986d422c81d8e657657 100644
--- a/apps/templates/_modal.html
+++ b/apps/templates/_modal.html
@@ -1,4 +1,9 @@
 {% load i18n %}
+<style>
+.modal-body {
+    padding: 0px 20px 0px 20px;
+}
+</style>
 <div aria-hidden="true" role="dialog" id="{% block modal_id %}{% endblock %}" class="modal inmodal">
     <div class="modal-dialog {% block modal_class %}{% endblock %}">
         <div class="modal-content animated fadeIn">
@@ -12,8 +17,10 @@
               {% endblock %}
             </div>
             <div class="modal-footer">
+              {% block modal_button %}
               <button data-dismiss="modal" class="btn btn-white" type="button">{% trans "Close" %}</button>
               <button class="btn btn-primary" type="button" id="{% block modal_confirm_id %}{% endblock %}">{% trans 'Confirm' %}</button>
+              {% endblock %}
             </div>
         </div>
     </div>
diff --git a/apps/templates/_nav.html b/apps/templates/_nav.html
index 409a46f151c5ed5e6ada846a5db738206d193001..e0d58080b851157e8cd676a1d5f795f68243bde1 100644
--- a/apps/templates/_nav.html
+++ b/apps/templates/_nav.html
@@ -61,7 +61,7 @@
 </li>
 <li id="audits">
     <a>
-        <i class="fa fa-coffee" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span>
+        <i class="fa fa-history" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span>
     </a>
     <ul class="nav nav-second-level">
         <li id="ftp-log"><a href="{% url 'audits:ftp-log-list' %}">{% trans 'FTP log' %}</a></li>
diff --git a/apps/terminal/api.py b/apps/terminal/api.py
index 8247ac27cb56221830f3012c2c8b0fbf11adc6b8..e625e17bcaf07e5c77a90a9ff4e60da4bcc8bec2 100644
--- a/apps/terminal/api.py
+++ b/apps/terminal/api.py
@@ -248,7 +248,7 @@ class CommandViewSet(viewsets.ViewSet):
 
 class SessionReplayViewSet(viewsets.ViewSet):
     serializer_class = ReplaySerializer
-    permission_classes = ()
+    permission_classes = (IsSuperUserOrAppUser,)
     session = None
 
     def gen_session_path(self):
diff --git a/apps/users/models/user.py b/apps/users/models/user.py
index 365f3428c2030f568852894a21de367a17b968c3..4674fe5192431a113cd03f058acad5405a41161b 100644
--- a/apps/users/models/user.py
+++ b/apps/users/models/user.py
@@ -45,7 +45,7 @@ class User(AbstractUser):
     wechat = models.CharField(max_length=128, blank=True, verbose_name=_('Wechat'))
     phone = models.CharField(max_length=20, blank=True, null=True, verbose_name=_('Phone'))
     otp_level = models.SmallIntegerField(default=0, choices=OTP_LEVEL_CHOICES, verbose_name=_('Enable OTP'))
-    otp_secret_key = models.CharField(max_length=16, blank=True, null=True)
+    _otp_secret_key = models.CharField(max_length=128, blank=True, null=True)
     # Todo: Auto generate key, let user download
     _private_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Private key'))
     _public_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Public key'))
@@ -55,7 +55,7 @@ class User(AbstractUser):
     created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
 
     def __str__(self):
-        return self.username
+        return '{0.name}({0.username})'.format(self)
 
     @property
     def password_raw(self):
@@ -70,6 +70,14 @@ class User(AbstractUser):
     def password_raw(self, password_raw_):
         self.set_password(password_raw_)
 
+    @property
+    def otp_secret_key(self):
+        return signer.unsign(self._otp_secret_key)
+
+    @otp_secret_key.setter
+    def otp_secret_key(self, item):
+        self._otp_secret_key = signer.sign(item).decode('utf-8')
+
     def get_absolute_url(self):
         return reverse('users:user-detail', args=(self.id,))
 
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index 71a0f742bb148b498a84b86815a00efa5e4ef87c..58aac783cfa1b7af98159098c31949bb57f9ee02 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -13,7 +13,7 @@ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_
 ```````````````
 使用 root 命令行输入::
 
-    $ docker run -d -p 8080:80 -p 2222:2222 registry.jumpserver.org/public/jumpserver:latest
+    $ docker run -d -p 8080:80 -p 2222:2222 registry.jumpserver.org/public/jumpserver:1.0.0
 
 访问
 ```````````````
@@ -42,10 +42,13 @@ XShell等工具请添加connection连接
 
  ::
 
-   docker run -d -p 8080:80 -p 2222:2222 -e DB_ENGINE=mysql -e DB_HOST=192.168.1.1 -e DB_PORT=3306 -e DB_USER=root -e DB_PASSWORD=xxx -e DB_NAME=jumpserver  registry.jumpserver.org/public/jumpserver:latest
+   docker run -d -p 8080:80 -p 2222:2222 -e DB_ENGINE=mysql -e DB_HOST=192.168.1.1 -e DB_PORT=3306 -e DB_USER=root -e DB_PASSWORD=xxx -e DB_NAME=jumpserver  registry.jumpserver.org/public/jumpserver:1.0.0
 
 
 仓库地址
 ```````````````
 
 https://github.com/jumpserver/Dockerfile
+
+
+
diff --git a/docs/step_by_step.rst b/docs/step_by_step.rst
index 21903a73bac2b5d03cd1ea1b20589a1498ccf272..484013e1bc1b6e2959a636b9dab70e051670bfff 100644
--- a/docs/step_by_step.rst
+++ b/docs/step_by_step.rst
@@ -49,7 +49,7 @@
     # 看到下面的提示符代表成功,以后运行 Jumpserver 都要先运行以上 source 命令,以下所有命令均在该虚拟环境中运行
     (py3) [root@localhost py3]
 
-二. 安装 Jumpserver 0.5.0
+二. 安装 Jumpserver 1.0.0
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 **2.1 下载或 Clone 项目**
@@ -201,7 +201,7 @@
 
 Luna 已改为纯前端,需要 Nginx 来运行访问
 
-访问(https://github.com/jumpserver/luna/releases)下载对应 release 包,直接解压,不需要编译
+访问(https://github.com/jumpserver/luna/releases)下载对应版本的 release 包,直接解压,不需要编译
 
 4.1 解压 Luna
 
@@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
       -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \
       -e JUMPSERVER_KEY_DIR=/config/guacamole/key \
       -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \
-      registry.jumpserver.org/public/guacamole:latest
+      registry.jumpserver.org/public/guacamole:1.0.0
 
 这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。
 
diff --git a/utils/2018_04_11_migrate_permissions.sh b/utils/2018_04_11_migrate_permissions.sh
index 5f98e5d4a30378bf57172d68bb9bbc671baea227..bbc29c3889f94945d718f3f86d8a215a96aed695 100644
--- a/utils/2018_04_11_migrate_permissions.sh
+++ b/utils/2018_04_11_migrate_permissions.sh
@@ -3,9 +3,10 @@
 
 python ../apps/manage.py shell << EOF
 from perms.models import *
+from assets.models import SystemUser
 
 for old in NodePermission.objects.all():
-    perm = asset_perm_model.objects.using(db_alias).create(
+    perm = AssetPermission.objects.create(
             name="{}-{}-{}".format(
                 old.node.value,
                 old.user_group.name,
@@ -20,5 +21,10 @@ for old in NodePermission.objects.all():
     perm.user_groups.add(old.user_group)
     perm.nodes.add(old.node)
     perm.system_users.add(old.system_user)
+
+    for s in SystemUser.objects.all():
+        nodes = list(s.nodes.all())
+        s.nodes.set([])
+        s.nodes.set(nodes)
 EOF