mirror of https://github.com/jumpserver/jumpserver
				
				
				
			[Feature] 完成资产授权和资产添加
							parent
							
								
									653c328e84
								
							
						
					
					
						commit
						2d3967872b
					
				| 
						 | 
				
			
			@ -23,7 +23,7 @@ from django.shortcuts import get_object_or_404
 | 
			
		|||
from django.db.models import Q, Count
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from common.mixins import CustomFilterMixin
 | 
			
		||||
from common.mixins import IDInFilterMixin
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
 | 
			
		||||
    get_user_granted_assets
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ from .utils import LabelFilter
 | 
			
		|||
logger = get_logger(__file__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet):
 | 
			
		||||
class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    API endpoint that allows Asset to be viewed or edited.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +56,7 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet):
 | 
			
		|||
        asset_group_id = self.request.query_params.get('asset_group_id')
 | 
			
		||||
        admin_user_id = self.request.query_params.get('admin_user_id')
 | 
			
		||||
        system_user_id = self.request.query_params.get('system_user_id')
 | 
			
		||||
        node_id = self.request.query_params.get("node_id")
 | 
			
		||||
 | 
			
		||||
        if cluster_id:
 | 
			
		||||
            queryset = queryset.filter(cluster__id=cluster_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +71,9 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet):
 | 
			
		|||
            system_user = get_object_or_404(SystemUser, id=system_user_id)
 | 
			
		||||
            clusters = system_user.get_clusters()
 | 
			
		||||
            queryset = queryset.filter(cluster__in=clusters)
 | 
			
		||||
        if node_id:
 | 
			
		||||
            node = get_object_or_404(Node, id=node_id)
 | 
			
		||||
            queryset = queryset.filter(nodes__key__startswith=node.key)
 | 
			
		||||
        return queryset
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +90,7 @@ class UserAssetListView(generics.ListAPIView):
 | 
			
		|||
        return queryset
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AssetGroupViewSet(CustomFilterMixin, BulkModelViewSet):
 | 
			
		||||
class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    Asset group api set, for add,delete,update,list,retrieve resource
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +124,7 @@ class GroupAddAssetsApi(generics.UpdateAPIView):
 | 
			
		|||
            return Response({'error': serializer.errors}, status=400)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClusterViewSet(CustomFilterMixin, BulkModelViewSet):
 | 
			
		||||
class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    Cluster api set, for add,delete,update,list,retrieve resource
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +165,7 @@ class ClusterAddAssetsApi(generics.UpdateAPIView):
 | 
			
		|||
            return Response({'error': serializer.errors}, status=400)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminUserViewSet(CustomFilterMixin, BulkModelViewSet):
 | 
			
		||||
class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    Admin user api set, for add,delete,update,list,retrieve resource
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +201,7 @@ class SystemUserViewSet(BulkModelViewSet):
 | 
			
		|||
    permission_classes = (IsSuperUserOrAppUser,)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AssetListUpdateApi(CustomFilterMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
 | 
			
		||||
    """
 | 
			
		||||
    Asset bulk update api
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -318,8 +322,8 @@ class NodeViewSet(BulkModelViewSet):
 | 
			
		|||
    serializer_class = serializers.NodeSerializer
 | 
			
		||||
 | 
			
		||||
    def perform_create(self, serializer):
 | 
			
		||||
        child_id = Node.root().get_next_child_id()
 | 
			
		||||
        serializer.validated_data["id"] = child_id
 | 
			
		||||
        child_key = Node.root().get_next_child_key()
 | 
			
		||||
        serializer.validated_data["key"] = child_key
 | 
			
		||||
        serializer.save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -330,17 +334,20 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
 | 
			
		|||
    instance = None
 | 
			
		||||
 | 
			
		||||
    def post(self, request, *args, **kwargs):
 | 
			
		||||
        if not request.data.get("name"):
 | 
			
		||||
            request.data["name"] = _("New node {}").format(
 | 
			
		||||
                Node.root().get_next_child_id().split(":")[-1]
 | 
			
		||||
        if not request.data.get("value"):
 | 
			
		||||
            request.data["value"] = _("New node {}").format(
 | 
			
		||||
                Node.root().get_next_child_key().split(":")[-1]
 | 
			
		||||
            )
 | 
			
		||||
        return super().post(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def create(self, request, *args, **kwargs):
 | 
			
		||||
        instance = self.get_object()
 | 
			
		||||
        name = request.data.get("name")
 | 
			
		||||
        node = instance.create_child(name=name)
 | 
			
		||||
        return Response({"id": node.id, "name": node.name}, status=201)
 | 
			
		||||
        value = request.data.get("value")
 | 
			
		||||
        node = instance.create_child(value=value)
 | 
			
		||||
        return Response(
 | 
			
		||||
            {"id": node.id, "key": node.key, "value": node.value},
 | 
			
		||||
            status=201,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        instance = self.get_object()
 | 
			
		||||
| 
						 | 
				
			
			@ -348,5 +355,5 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
 | 
			
		|||
            children = instance.get_all_children()
 | 
			
		||||
        else:
 | 
			
		||||
            children = instance.get_children()
 | 
			
		||||
        response = [{"id": node.id, "name": node.name} for node in children]
 | 
			
		||||
        response = [{"id": node.id, "key": node.key, "value": node.value} for node in children]
 | 
			
		||||
        return Response(response, status=200)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,14 @@ class Node(models.Model):
 | 
			
		|||
    date_create = models.DateTimeField(auto_now_add=True)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.value
 | 
			
		||||
        return self.full_value
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def full_value(self):
 | 
			
		||||
        if self == self.__class__.root():
 | 
			
		||||
            return self.value
 | 
			
		||||
        else:
 | 
			
		||||
            return '{}/{}'.format( self.value, self.parent.full_value)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def level(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +59,21 @@ class Node(models.Model):
 | 
			
		|||
        assets = Asset.objects.filter(nodes__in=children)
 | 
			
		||||
        return assets
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def parent(self):
 | 
			
		||||
        if self.key == "0":
 | 
			
		||||
            return self.__class__.root()
 | 
			
		||||
        elif not self.key.startswith("0"):
 | 
			
		||||
            return self.__class__.root()
 | 
			
		||||
 | 
			
		||||
        parent_key = ":".join(self.key.split(":")[:-1])
 | 
			
		||||
        try:
 | 
			
		||||
            parent = self.__class__.objects.get(key=parent_key)
 | 
			
		||||
        except Node.DoesNotExist:
 | 
			
		||||
            return self.__class__.root()
 | 
			
		||||
        else:
 | 
			
		||||
            return parent
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def root(cls):
 | 
			
		||||
        obj, created = cls.objects.get_or_create(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -328,11 +328,7 @@ class NodeSerializer(serializers.ModelSerializer):
 | 
			
		|||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_parent(obj):
 | 
			
		||||
        if obj.key == "0":
 | 
			
		||||
            return "#"
 | 
			
		||||
        if not obj.key.startswith("0"):
 | 
			
		||||
            return "0"
 | 
			
		||||
        return ":".join(obj.key.split(":")[:-1])
 | 
			
		||||
        return obj.parent.id
 | 
			
		||||
 | 
			
		||||
    def get_fields(self):
 | 
			
		||||
        fields = super().get_fields()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,7 +64,6 @@
 | 
			
		|||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% include 'assets/_asset_import_modal.html' %}
 | 
			
		||||
{#{% include 'assets/_asset_bulk_update_modal.html' %}#}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block custom_foot_js %}
 | 
			
		||||
| 
						 | 
				
			
			@ -126,15 +125,7 @@ $(document).ready(function(){
 | 
			
		|||
})
 | 
			
		||||
.on('click', '.labels li', function () {
 | 
			
		||||
    var val = $(this).text();
 | 
			
		||||
    {#var origin_val = $("#asset_list_table_filter input").val();#}
 | 
			
		||||
    {#var new_val;#}
 | 
			
		||||
    {#if (origin_val === "") {#}
 | 
			
		||||
    {#    new_val = val;#}
 | 
			
		||||
    {# } else { #}
 | 
			
		||||
    {#    new_val = origin_val + " " + val;#}
 | 
			
		||||
    {# } #}
 | 
			
		||||
    $("#asset_list_table_filter input").val(val);
 | 
			
		||||
    {#$('#asset_list_table').DataTable().search(val).draw();#}
 | 
			
		||||
    jumpserver.table.search(val).draw();
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.btn_export', function () {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,13 +5,7 @@
 | 
			
		|||
{% block custom_head_css_js %}
 | 
			
		||||
    <link href="{% static 'css/plugins/jstree/style.min.css' %}" rel="stylesheet">
 | 
			
		||||
    <link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
 | 
			
		||||
{#    <link href="{% static 'css/plugins/ztree/demo.css' %}" rel="stylesheet">#}
 | 
			
		||||
    <script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
 | 
			
		||||
    <script type="text/javascript">
 | 
			
		||||
		$(document).ready(function(){
 | 
			
		||||
 | 
			
		||||
		});
 | 
			
		||||
	</script>
 | 
			
		||||
	<style type="text/css">
 | 
			
		||||
        div#rMenu {
 | 
			
		||||
            position:absolute;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +39,6 @@
 | 
			
		|||
           <div class="ibox float-e-margins">
 | 
			
		||||
               <div class="ibox-content mailbox-content" style="padding-top: 0">
 | 
			
		||||
                   <div class="file-manager ">
 | 
			
		||||
{#                       <h5>Tree View</h5>#}
 | 
			
		||||
                       <div id="assetTree" class="ztree">
 | 
			
		||||
                       </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +48,18 @@
 | 
			
		|||
           </div>
 | 
			
		||||
       </div>
 | 
			
		||||
       <div class="col-lg-9 animated fadeInRight">
 | 
			
		||||
           <div class="row">
 | 
			
		||||
               <div class="mail-box-header">
 | 
			
		||||
                   <div class="uc pull-left m-r-5"><a href="{% url "assets:asset-create" %}" class="btn btn-sm btn-primary"> {% trans "Add asset" %} </a></div>
 | 
			
		||||
                   <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">
 | 
			
		||||
| 
						 | 
				
			
			@ -72,8 +74,6 @@
 | 
			
		|||
                               <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 'Port' %}</th>
 | 
			
		||||
                               <th class="text-center">{% trans 'Cluster' %}</th>
 | 
			
		||||
                               <th class="text-center">{% trans 'Hardware' %}</th>
 | 
			
		||||
                               <th class="text-center">{% trans 'Active' %}</th>
 | 
			
		||||
                               <th class="text-center">{% trans 'Reachable' %}</th>
 | 
			
		||||
| 
						 | 
				
			
			@ -98,9 +98,6 @@
 | 
			
		|||
                           </div>
 | 
			
		||||
                       </div>
 | 
			
		||||
                   </div>
 | 
			
		||||
               </div>
 | 
			
		||||
           </div>
 | 
			
		||||
           <div class="row">
 | 
			
		||||
           </div>
 | 
			
		||||
       </div>
 | 
			
		||||
   </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -108,220 +105,393 @@
 | 
			
		|||
 | 
			
		||||
<div id="rMenu">
 | 
			
		||||
    <ul class="dropdown-menu">
 | 
			
		||||
        <li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>重命名</a></li>
 | 
			
		||||
        <li id="m_add" tabindex="-1" onclick="addTreeNode();"><a>添加节点</a></li>
 | 
			
		||||
        <li id="m_add" class="btn-create-asset" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Create asset' %}</a></li>
 | 
			
		||||
        <li class="divider"></li>
 | 
			
		||||
        <li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>删除节点</a></li>
 | 
			
		||||
        <li id="m_add" 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 class="divider"></li>
 | 
			
		||||
        <li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>{% trans 'Delete node' %}</a></li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% include 'assets/_asset_import_modal.html' %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block custom_foot_js %}
 | 
			
		||||
<script src="{% static 'js/plugins/jstree/jstree.min.js' %}"></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    var zTree, rMenu;
 | 
			
		||||
    function initTable() {
 | 
			
		||||
        var options = {
 | 
			
		||||
            ele: $('#asset_list_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: 4, createdCell: function (td, cellData, rowData) {
 | 
			
		||||
                     $(td).html(rowData.cluster_name)
 | 
			
		||||
                }},
 | 
			
		||||
                {targets: 5, createdCell: function (td, cellData, rowData) {
 | 
			
		||||
                    $(td).html(rowData.hardware_info)
 | 
			
		||||
                }},
 | 
			
		||||
                {targets: 6, 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: 7, 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: 8, 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)
 | 
			
		||||
                }}
 | 
			
		||||
            ],
 | 
			
		||||
            ajax_url: '{% url "api-assets:asset-list" %}',
 | 
			
		||||
            columns: [
 | 
			
		||||
                {data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" },
 | 
			
		||||
                {data: "cluster"},
 | 
			
		||||
                {data: "cpu_cores"}, {data: "is_active", orderable: false },
 | 
			
		||||
                {data: "is_connective", orderable: false}, {data: "id", orderable: false }
 | 
			
		||||
            ],
 | 
			
		||||
            op_html: $('#actions').html()
 | 
			
		||||
        };
 | 
			
		||||
        return jumpserver.initServerSideDataTable(options);
 | 
			
		||||
var zTree, rMenu, asset_table;
 | 
			
		||||
function initTable() {
 | 
			
		||||
    var options = {
 | 
			
		||||
        ele: $('#asset_list_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)
 | 
			
		||||
            }}
 | 
			
		||||
        ],
 | 
			
		||||
        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 }
 | 
			
		||||
        ],
 | 
			
		||||
        op_html: $('#actions').html()
 | 
			
		||||
    };
 | 
			
		||||
    asset_table = jumpserver.initServerSideDataTable(options);
 | 
			
		||||
    return asset_table
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function addTreeNode() {
 | 
			
		||||
	hideRMenu();
 | 
			
		||||
	var parentNode = zTree.getSelectedNodes()[0];
 | 
			
		||||
	if (!parentNode){
 | 
			
		||||
	    return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function OnRightClick(event, treeId, treeNode) {
 | 
			
		||||
	    if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length == 0) {
 | 
			
		||||
			zTree.cancelSelectedNode();
 | 
			
		||||
			showRMenu("root", event.clientX, event.clientY);
 | 
			
		||||
		} else if (treeNode && !treeNode.noR) {
 | 
			
		||||
			zTree.selectNode(treeNode);
 | 
			
		||||
			showRMenu("node", event.clientX, event.clientY);
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	function showRMenu(type, x, y) {
 | 
			
		||||
		$("#rMenu ul").show();
 | 
			
		||||
		if (type === "root") {
 | 
			
		||||
			return
 | 
			
		||||
		} else {
 | 
			
		||||
			$("#m_del").show();
 | 
			
		||||
			$("#m_check").show();
 | 
			
		||||
			$("#m_unCheck").show();
 | 
			
		||||
		}
 | 
			
		||||
        {#y += $("#page-wrapper")[0].scrollTop;#}
 | 
			
		||||
        {#x += $("#page-wrapper")[0].scrollLeft;#}
 | 
			
		||||
        x -= 220;
 | 
			
		||||
        {#y -= 100;#}
 | 
			
		||||
        {#y += document.body.scrollTop;#}
 | 
			
		||||
        {#x += document.body.scrollLeft;#}
 | 
			
		||||
        rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
 | 
			
		||||
 | 
			
		||||
		$("body").bind("mousedown", onBodyMouseDown);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function beforeClick(treeId, treeNode, clickFlag) {
 | 
			
		||||
        return true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	function onClick(event, treeId, treeNode, clickFlag) {
 | 
			
		||||
		showLog("On click");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function showLog(str) {
 | 
			
		||||
        console.log(str)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function hideRMenu() {
 | 
			
		||||
		if (rMenu) rMenu.css({"visibility": "hidden"});
 | 
			
		||||
		$("body").unbind("mousedown", onBodyMouseDown);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function onBodyMouseDown(event){
 | 
			
		||||
		if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) {
 | 
			
		||||
			rMenu.css({"visibility" : "hidden"});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function addTreeNode() {
 | 
			
		||||
		hideRMenu();
 | 
			
		||||
		var parentNode = zTree.getSelectedNodes()[0];
 | 
			
		||||
		if (!parentNode){
 | 
			
		||||
		    return
 | 
			
		||||
    var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.id );
 | 
			
		||||
    $.post(url,  {}, function (data, status){
 | 
			
		||||
        if (status === "success") {
 | 
			
		||||
            var newNode = {
 | 
			
		||||
                name: data["value"],
 | 
			
		||||
                id: data["id"],
 | 
			
		||||
                pId: parentNode.id
 | 
			
		||||
            };
 | 
			
		||||
            newNode.checked = zTree.getSelectedNodes()[0].checked;
 | 
			
		||||
            zTree.addNodes(parentNode, 0, newNode);
 | 
			
		||||
        } else {
 | 
			
		||||
            alert("{% trans 'Create node failed' %}")
 | 
			
		||||
        }
 | 
			
		||||
        var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.id );
 | 
			
		||||
        $.post(url,  {}, function (data, status){
 | 
			
		||||
            if (status === "success") {
 | 
			
		||||
                var newNode = { name:data["name"], id:data["id"],  pId: parentNode.id };
 | 
			
		||||
                newNode.checked = zTree.getSelectedNodes()[0].checked;
 | 
			
		||||
                zTree.addNodes(parentNode, 0, newNode);
 | 
			
		||||
            } else {
 | 
			
		||||
                alert("{% trans 'Create node failed' %}")
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function removeTreeNode() {
 | 
			
		||||
	hideRMenu();
 | 
			
		||||
	var current_node = zTree.getSelectedNodes()[0];
 | 
			
		||||
	if (!current_node){
 | 
			
		||||
	    return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	if (current_node.children && current_node.children.length > 0) {
 | 
			
		||||
		alert("{% trans 'Have child node, cancel' %}")
 | 
			
		||||
	} else {
 | 
			
		||||
        var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id );
 | 
			
		||||
		$.ajax({
 | 
			
		||||
            url: url,
 | 
			
		||||
            method: "DELETE",
 | 
			
		||||
            success: function () {
 | 
			
		||||
                zTree.removeNode(current_node);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	function removeTreeNode() {
 | 
			
		||||
		hideRMenu();
 | 
			
		||||
		var current_node = zTree.getSelectedNodes()[0];
 | 
			
		||||
		if (!current_node){
 | 
			
		||||
		    return
 | 
			
		||||
        }
 | 
			
		||||
function editTreeNode() {
 | 
			
		||||
    hideRMenu();
 | 
			
		||||
	var current_node = zTree.getSelectedNodes()[0];
 | 
			
		||||
	if (!current_node){
 | 
			
		||||
	    return
 | 
			
		||||
    }
 | 
			
		||||
    zTree.editName(current_node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		if (current_node.children && current_node.children.length > 0) {
 | 
			
		||||
			alert("{% trans 'Have child node, cancel' %}")
 | 
			
		||||
		} else {
 | 
			
		||||
            var url = "{% url 'api-assets:node-detail' pk='0:0' %}".replace("0:0", current_node.id );
 | 
			
		||||
			$.ajax({
 | 
			
		||||
                url: url,
 | 
			
		||||
                method: "DELETE",
 | 
			
		||||
                success: function () {
 | 
			
		||||
                    zTree.removeNode(current_node);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
function OnRightClick(event, treeId, treeNode) {
 | 
			
		||||
    if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length === 0) {
 | 
			
		||||
		zTree.cancelSelectedNode();
 | 
			
		||||
		showRMenu("root", event.clientX, event.clientY);
 | 
			
		||||
	} else if (treeNode && !treeNode.noR) {
 | 
			
		||||
		zTree.selectNode(treeNode);
 | 
			
		||||
		showRMenu("node", event.clientX, event.clientY);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	function onRenameNode(event, treeId, treeNode, isCancel){
 | 
			
		||||
        var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.id);
 | 
			
		||||
        var data = {"value": treeNode.name};
 | 
			
		||||
        if (isCancel){
 | 
			
		||||
            return
 | 
			
		||||
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"});
 | 
			
		||||
 | 
			
		||||
	$("body").bind("mousedown", onBodyMouseDown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function beforeClick(treeId, treeNode, clickFlag) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hideRMenu() {
 | 
			
		||||
	if (rMenu) rMenu.css({"visibility": "hidden"});
 | 
			
		||||
	$("body").unbind("mousedown", onBodyMouseDown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onBodyMouseDown(event){
 | 
			
		||||
	if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) {
 | 
			
		||||
		rMenu.css({"visibility" : "hidden"});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function onRename(event, treeId, treeNode, isCancel){
 | 
			
		||||
    var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.id);
 | 
			
		||||
    var data = {"value": treeNode.name};
 | 
			
		||||
    if (isCancel){
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
    APIUpdateAttr({
 | 
			
		||||
        url: url,
 | 
			
		||||
        body: JSON.stringify(data),
 | 
			
		||||
        method: "PATCH"
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onSelected(event, treeNode) {
 | 
			
		||||
    var url = asset_table.ajax.url();
 | 
			
		||||
    url = setUrlParam(url, "node_id", treeNode.id);
 | 
			
		||||
    asset_table.ajax.url(url);
 | 
			
		||||
    asset_table.ajax.reload();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function selectQueryNode() {
 | 
			
		||||
    var node_id = $.getUrlParam("node");
 | 
			
		||||
    if (node_id !== null) {
 | 
			
		||||
        var node = zTree.getNodesByParam("id", node_id, null);
 | 
			
		||||
        if (node){
 | 
			
		||||
            zTree.selectNode(node[0]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initTree() {
 | 
			
		||||
    var setting = {
 | 
			
		||||
        view: {
 | 
			
		||||
            dblClickExpand: false,
 | 
			
		||||
            showLine: true
 | 
			
		||||
        },
 | 
			
		||||
        data: {
 | 
			
		||||
            simpleData: {
 | 
			
		||||
                enable: true
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        callback: {
 | 
			
		||||
            onRightClick: OnRightClick,
 | 
			
		||||
            beforeClick: beforeClick,
 | 
			
		||||
            onRename: onRename,
 | 
			
		||||
            onSelected: onSelected
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    var zNodes = [];
 | 
			
		||||
    $.get("{% url 'api-assets:node-list' %}", function(data, status){
 | 
			
		||||
        $.each(data, function (index, value) {
 | 
			
		||||
            value["pId"] = value["parent"];
 | 
			
		||||
            if (value["key"] === "0") {
 | 
			
		||||
                value["open"] = true;
 | 
			
		||||
            }
 | 
			
		||||
            value["name"] = value["value"]
 | 
			
		||||
        });
 | 
			
		||||
        zNodes = data;
 | 
			
		||||
        $.fn.zTree.init($("#assetTree"), setting, zNodes);
 | 
			
		||||
        zTree = $.fn.zTree.getZTreeObj("assetTree");
 | 
			
		||||
		rMenu = $("#rMenu");
 | 
			
		||||
		selectQueryNode();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$(document).ready(function(){
 | 
			
		||||
    initTable();
 | 
			
		||||
    initTree();
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.labels li', function () {
 | 
			
		||||
    var val = $(this).text();
 | 
			
		||||
    $("#asset_list_table_filter input").val(val);
 | 
			
		||||
    jumpserver.table.search(val).draw();
 | 
			
		||||
 })
 | 
			
		||||
.on('click', '.btn_export', function () {
 | 
			
		||||
    var $data_table = $('#asset_list_table').DataTable();
 | 
			
		||||
    var rows = $data_table.rows('.selected').data();
 | 
			
		||||
    var assets = [];
 | 
			
		||||
    $.each(rows, function (index, obj) {
 | 
			
		||||
        assets.push(obj.id)
 | 
			
		||||
    });
 | 
			
		||||
    $.ajax({
 | 
			
		||||
        url: "{% url "assets:asset-export" %}",
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        data: JSON.stringify({assets_id: assets}),
 | 
			
		||||
        dataType: "json",
 | 
			
		||||
        success: function (data, textStatus) {
 | 
			
		||||
            window.open(data.redirect)
 | 
			
		||||
        },
 | 
			
		||||
        error: function () {
 | 
			
		||||
            toastr.error('Export failed');
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
.on('click', '#btn_asset_import', function () {
 | 
			
		||||
    var $form = $('#fm_asset_import');
 | 
			
		||||
    $form.find('.help-block').remove();
 | 
			
		||||
    function success (data) {
 | 
			
		||||
        if (data.valid === false) {
 | 
			
		||||
            $('<span />', {class: 'help-block text-danger'}).html(data.msg).insertAfter($('#id_assets'));
 | 
			
		||||
        } else {
 | 
			
		||||
            $('#id_created').html(data.created_info);
 | 
			
		||||
            $('#id_created_detail').html(data.created.join(', '));
 | 
			
		||||
            $('#id_updated').html(data.updated_info);
 | 
			
		||||
            $('#id_updated_detail').html(data.updated.join(', '));
 | 
			
		||||
            $('#id_failed').html(data.failed_info);
 | 
			
		||||
            $('#id_failed_detail').html(data.failed.join(', '));
 | 
			
		||||
            var $data_table = $('#asset_list_table').DataTable();
 | 
			
		||||
            $data_table.ajax.reload();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $form.ajaxSubmit({success: success});
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.btn-create-asset', function () {
 | 
			
		||||
    var url = "{% url 'assets:asset-create' %}";
 | 
			
		||||
    var nodes = zTree.getSelectedNodes();
 | 
			
		||||
    var current_node;
 | 
			
		||||
    if (nodes && nodes.length ===1 ){
 | 
			
		||||
        current_node = nodes[0];
 | 
			
		||||
        url += "?node_id=" + current_node.id;
 | 
			
		||||
    }
 | 
			
		||||
    window.open(url);
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.btn_asset_delete', function () {
 | 
			
		||||
    var $this = $(this);
 | 
			
		||||
    var $data_table = $("#asset_list_table").DataTable();
 | 
			
		||||
    var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
 | 
			
		||||
    var uid = $this.data('uid');
 | 
			
		||||
    var the_url = '{% url "api-assets:asset-detail" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", uid);
 | 
			
		||||
    objectDelete($this, name, the_url);
 | 
			
		||||
    setTimeout( function () {
 | 
			
		||||
        $data_table.ajax.reload();
 | 
			
		||||
    }, 3000);
 | 
			
		||||
})
 | 
			
		||||
.on('click', '#btn_bulk_update', function () {
 | 
			
		||||
    var action = $('#slct_bulk_update').val();
 | 
			
		||||
    var $data_table = $('#asset_list_table').DataTable();
 | 
			
		||||
    var id_list = [];
 | 
			
		||||
    $data_table.rows({selected: true}).every(function(){
 | 
			
		||||
        id_list.push(this.data().id);
 | 
			
		||||
    });
 | 
			
		||||
    if (id_list.length === 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    var the_url = "{% url 'api-assets:asset-list' %}";
 | 
			
		||||
 | 
			
		||||
    function doDeactive() {
 | 
			
		||||
        var data = [];
 | 
			
		||||
        $.each(id_list, function(index, object_id) {
 | 
			
		||||
            var obj = {"pk": object_id, "is_active": false};
 | 
			
		||||
            data.push(obj);
 | 
			
		||||
        });
 | 
			
		||||
        function success() {
 | 
			
		||||
            asset_table.ajax.reload()
 | 
			
		||||
        }
 | 
			
		||||
        APIUpdateAttr({
 | 
			
		||||
            url: url,
 | 
			
		||||
            url: the_url,
 | 
			
		||||
            method: 'PATCH',
 | 
			
		||||
            body: JSON.stringify(data),
 | 
			
		||||
            method: "PATCH"
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	function editTreeNode() {
 | 
			
		||||
        hideRMenu();
 | 
			
		||||
		var current_node = zTree.getSelectedNodes()[0];
 | 
			
		||||
		if (!current_node){
 | 
			
		||||
		    return
 | 
			
		||||
        }
 | 
			
		||||
        zTree.editName(current_node);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function initTree() {
 | 
			
		||||
        var setting = {
 | 
			
		||||
            view: {
 | 
			
		||||
                dblClickExpand: false,
 | 
			
		||||
                showLine: true
 | 
			
		||||
            },
 | 
			
		||||
            data: {
 | 
			
		||||
                simpleData: {
 | 
			
		||||
                    enable: true
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            callback: {
 | 
			
		||||
                onRightClick: OnRightClick,
 | 
			
		||||
                beforeClick: beforeClick,
 | 
			
		||||
				onClick: onClick,
 | 
			
		||||
                onRename: onRenameNode
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        var zNodes = [];
 | 
			
		||||
        $.get("{% url 'api-assets:node-list' %}", function(data, status){
 | 
			
		||||
            $.each(data, function (index, value) {
 | 
			
		||||
                value["pId"] = value["parent"];
 | 
			
		||||
                if (value["key"] === "0") {
 | 
			
		||||
                    value["open"] = true;
 | 
			
		||||
                }
 | 
			
		||||
                value["name"] = value["value"]
 | 
			
		||||
            });
 | 
			
		||||
            zNodes = data;
 | 
			
		||||
            $.fn.zTree.init($("#assetTree"), setting, zNodes);
 | 
			
		||||
            zTree = $.fn.zTree.getZTreeObj("assetTree");
 | 
			
		||||
			rMenu = $("#rMenu");
 | 
			
		||||
            success: success
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    $(document).ready(function(){
 | 
			
		||||
        initTable();
 | 
			
		||||
        initTree();
 | 
			
		||||
    });
 | 
			
		||||
    function doActive() {
 | 
			
		||||
        var data = [];
 | 
			
		||||
        $.each(id_list, function(index, object_id) {
 | 
			
		||||
            var obj = {"pk": object_id, "is_active": true};
 | 
			
		||||
            data.push(obj);
 | 
			
		||||
        });
 | 
			
		||||
        function success() {
 | 
			
		||||
            asset_table.ajax.reload()
 | 
			
		||||
        }
 | 
			
		||||
        APIUpdateAttr({
 | 
			
		||||
            url: the_url,
 | 
			
		||||
            method: 'PATCH',
 | 
			
		||||
            body: JSON.stringify(data),
 | 
			
		||||
            success: success
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    function doDelete() {
 | 
			
		||||
        swal({
 | 
			
		||||
            title: "{% trans 'Are you sure?' %}",
 | 
			
		||||
            text: "{% trans 'This will delete the selected assets !!!' %}",
 | 
			
		||||
            type: "warning",
 | 
			
		||||
            showCancelButton: true,
 | 
			
		||||
            confirmButtonColor: "#DD6B55",
 | 
			
		||||
            confirmButtonText: "{% trans 'Confirm' %}",
 | 
			
		||||
            closeOnConfirm: false
 | 
			
		||||
        }, function() {
 | 
			
		||||
            var success = function() {
 | 
			
		||||
                var msg = "{% trans 'Asset Deleted.' %}";
 | 
			
		||||
                swal("{% trans 'Asset Delete' %}", msg, "success");
 | 
			
		||||
                $('#asset_list_table').DataTable().ajax.reload();
 | 
			
		||||
            };
 | 
			
		||||
            var fail = function() {
 | 
			
		||||
                var msg = "{% trans 'Asset Deleting failed.' %}";
 | 
			
		||||
                swal("{% trans 'Asset Delete' %}", msg, "error");
 | 
			
		||||
            };
 | 
			
		||||
            var url_delete = the_url + '?id__in=' + JSON.stringify(id_list);
 | 
			
		||||
            APIUpdateAttr({
 | 
			
		||||
                url: url_delete,
 | 
			
		||||
                method: 'DELETE',
 | 
			
		||||
                success: success,
 | 
			
		||||
                error: fail
 | 
			
		||||
            });
 | 
			
		||||
            $data_table.ajax.reload();
 | 
			
		||||
            jumpserver.checked = false;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    function doUpdate() {
 | 
			
		||||
        var id_list_string = id_list.join(',');
 | 
			
		||||
        var url = "{% url 'assets:asset-bulk-update' %}?assets_id=" + id_list_string;
 | 
			
		||||
        location.href = url
 | 
			
		||||
    }
 | 
			
		||||
    switch(action) {
 | 
			
		||||
        case 'deactive':
 | 
			
		||||
            doDeactive();
 | 
			
		||||
            break;
 | 
			
		||||
        case 'delete':
 | 
			
		||||
            doDelete();
 | 
			
		||||
            break;
 | 
			
		||||
        case 'update':
 | 
			
		||||
            doUpdate();
 | 
			
		||||
            break;
 | 
			
		||||
        case 'active':
 | 
			
		||||
            doActive();
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ from common.mixins import JSONResponseMixin
 | 
			
		|||
from common.utils import get_object_or_none, get_logger, is_uuid
 | 
			
		||||
from common.const import create_success_msg, update_success_msg
 | 
			
		||||
from .. import forms
 | 
			
		||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser, Label
 | 
			
		||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser, Label, Node
 | 
			
		||||
from ..hands import AdminUserRequiredMixin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,13 +41,12 @@ logger = get_logger(__file__)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class AssetListView(AdminUserRequiredMixin, TemplateView):
 | 
			
		||||
    template_name = 'assets/asset_list.html'
 | 
			
		||||
    template_name = 'assets/tree.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
            'app': _('Assets'),
 | 
			
		||||
            'action': _('Asset list'),
 | 
			
		||||
            'system_users': SystemUser.objects.all(),
 | 
			
		||||
            'labels': Label.objects.all().order_by('name'),
 | 
			
		||||
        }
 | 
			
		||||
        kwargs.update(context)
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +80,16 @@ class AssetCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
 | 
			
		|||
    #     asset.save()
 | 
			
		||||
    #     return super().form_valid(form)
 | 
			
		||||
 | 
			
		||||
    def get_form(self, form_class=None):
 | 
			
		||||
        form = super().get_form(form_class=form_class)
 | 
			
		||||
        node_id = self.request.GET.get("node_id")
 | 
			
		||||
        if node_id:
 | 
			
		||||
            node = get_object_or_none(Node, id=node_id)
 | 
			
		||||
        else:
 | 
			
		||||
            node = Node.root()
 | 
			
		||||
        form["nodes"].initial = node
 | 
			
		||||
        return form
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
            'app': _('Assets'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ from django.views.generic import TemplateView
 | 
			
		|||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from common.mixins import AdminUserRequiredMixin
 | 
			
		||||
from ..models import Label
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['TreeView']
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +18,7 @@ class TreeView(AdminUserRequiredMixin, TemplateView):
 | 
			
		|||
        context = {
 | 
			
		||||
            'app': _('Assets'),
 | 
			
		||||
            'action': _('Tree view'),
 | 
			
		||||
            'labels': Label.objects.all(),
 | 
			
		||||
        }
 | 
			
		||||
        kwargs.update(context)
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,9 +47,9 @@ class JSONResponseMixin(object):
 | 
			
		|||
        return JsonResponse(context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CustomFilterMixin(object):
 | 
			
		||||
class IDInFilterMixin(object):
 | 
			
		||||
    def filter_queryset(self, queryset):
 | 
			
		||||
        queryset = super(CustomFilterMixin, self).filter_queryset(queryset)
 | 
			
		||||
        queryset = super(IDInFilterMixin, self).filter_queryset(queryset)
 | 
			
		||||
        id_list = self.request.query_params.get('id__in')
 | 
			
		||||
        if id_list:
 | 
			
		||||
            import json
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,10 +9,9 @@ from rest_framework import viewsets
 | 
			
		|||
from common.utils import get_object_or_none
 | 
			
		||||
from users.permissions import IsValidUser, IsSuperUser, IsAppUser, IsSuperUserOrAppUser
 | 
			
		||||
from .utils import get_user_granted_assets, get_user_granted_asset_groups, \
 | 
			
		||||
    get_user_asset_permissions, get_user_group_asset_permissions, \
 | 
			
		||||
    get_user_group_granted_assets, get_user_group_granted_asset_groups
 | 
			
		||||
from .models import AssetPermission, NodePermission
 | 
			
		||||
from .hands import AssetGrantedSerializer, User, UserGroup, AssetGroup, Asset, \
 | 
			
		||||
from .hands import AssetGrantedSerializer, User, UserGroup, Node, Asset, \
 | 
			
		||||
    AssetGroup, AssetGroupGrantedSerializer, SystemUser, MyAssetGroupGrantedSerializer
 | 
			
		||||
from . import serializers
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,24 +29,12 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
 | 
			
		|||
            return serializers.AssetPermissionListSerializer
 | 
			
		||||
        return self.serializer_class
 | 
			
		||||
 | 
			
		||||
    # def get_queryset(self):
 | 
			
		||||
    #     queryset = super(AssetPermissionViewSet, self).get_queryset()
 | 
			
		||||
    #     user_id = self.request.query_params.get('user', '')
 | 
			
		||||
    #     user_group_id = self.request.query_params.get('user_group', '')
 | 
			
		||||
    #
 | 
			
		||||
    #     if user_id and user_id.isdigit():
 | 
			
		||||
    #         user = get_object_or_404(User, id=int(user_id))
 | 
			
		||||
    #         queryset = get_user_asset_permissions(user)
 | 
			
		||||
    #
 | 
			
		||||
    #     if user_group_id:
 | 
			
		||||
    #         user_group = get_object_or_404(UserGroup, id=user_group_id)
 | 
			
		||||
    #         queryset = get_user_group_asset_permissions(user_group)
 | 
			
		||||
    #     return queryset
 | 
			
		||||
 | 
			
		||||
    # def get_serializer_class(self):
 | 
			
		||||
    #     if getattr(self, 'user_id', ''):
 | 
			
		||||
    #         return serializers.UserAssetPermissionCreateUpdateSerializer
 | 
			
		||||
    #     return serializers.AssetPermissionCreateUpdateSerializer
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        queryset = super().get_queryset()
 | 
			
		||||
        node_id = self.request.query_params.get('node_id')
 | 
			
		||||
        if node_id:
 | 
			
		||||
            queryset = queryset.filter(node__id=node_id)
 | 
			
		||||
        return queryset
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
 | 
			
		||||
from users.utils import AdminUserRequiredMixin
 | 
			
		||||
from users.models import User, UserGroup
 | 
			
		||||
from assets.models import Asset, AssetGroup, SystemUser
 | 
			
		||||
from assets.models import Asset, AssetGroup, SystemUser, Node
 | 
			
		||||
from assets.serializers import AssetGrantedSerializer, AssetGroupGrantedSerializer, MyAssetGroupGrantedSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,56 +1,100 @@
 | 
			
		|||
{% extends '_base_list.html' %}
 | 
			
		||||
{% extends 'base.html' %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block table_search %}
 | 
			
		||||
{% block custom_head_css_js %}
 | 
			
		||||
    <link href="{% static 'css/plugins/jstree/style.min.css' %}" rel="stylesheet">
 | 
			
		||||
    <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>
 | 
			
		||||
	<style type="text/css">
 | 
			
		||||
        div#rMenu {
 | 
			
		||||
            position:absolute;
 | 
			
		||||
            visibility:hidden;
 | 
			
		||||
            text-align: left;
 | 
			
		||||
            top: 100%;
 | 
			
		||||
            left: 0;
 | 
			
		||||
            z-index: 1000;
 | 
			
		||||
            float: left;
 | 
			
		||||
            padding: 5px 0;
 | 
			
		||||
            margin: 2px 0 0;
 | 
			
		||||
            list-style: none;
 | 
			
		||||
            background-clip: padding-box;
 | 
			
		||||
        }
 | 
			
		||||
        div#rMenu li{
 | 
			
		||||
        	margin: 1px 0;
 | 
			
		||||
        	cursor: pointer;
 | 
			
		||||
        	{#list-style: none outside none;#}
 | 
			
		||||
        }
 | 
			
		||||
        .dropdown a:hover {
 | 
			
		||||
            background-color: #f1f1f1
 | 
			
		||||
        }
 | 
			
		||||
	</style>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block help_message %}
 | 
			
		||||
    <div class="alert alert-info help-message">
 | 
			
		||||
    </div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block table_container %}
 | 
			
		||||
<div class="uc pull-left m-r-5">
 | 
			
		||||
    <a href="{% url 'perms:asset-permission-create' %}" class="btn btn-sm btn-primary ">
 | 
			
		||||
        {% trans "Create permission" %}
 | 
			
		||||
    </a>
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="wrapper wrapper-content">
 | 
			
		||||
   <div class="row">
 | 
			
		||||
       <div class="col-lg-3">
 | 
			
		||||
           <div class="ibox float-e-margins">
 | 
			
		||||
               <div class="ibox-content mailbox-content" style="padding-top: 0">
 | 
			
		||||
                   <div class="file-manager ">
 | 
			
		||||
                       <div id="assetTree" class="ztree">
 | 
			
		||||
                       </div>
 | 
			
		||||
                       <div class="clearfix"></div>
 | 
			
		||||
                   </div>
 | 
			
		||||
               </div>
 | 
			
		||||
           </div>
 | 
			
		||||
       </div>
 | 
			
		||||
       <div class="col-lg-9 animated fadeInRight">
 | 
			
		||||
          <div class="mail-box-header">
 | 
			
		||||
              <div class="uc pull-left m-r-5">
 | 
			
		||||
                   <a class="btn btn-sm btn-primary btn-create-permission">
 | 
			
		||||
                       {% trans "Create permission" %}
 | 
			
		||||
                   </a>
 | 
			
		||||
              </div>
 | 
			
		||||
              <table class="table table-striped table-bordered table-hover" id="permission_list_table" >
 | 
			
		||||
                  <thead>
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <th class="text-center">
 | 
			
		||||
                          <input type="checkbox" id="check_all" class="ipt_check_all" >
 | 
			
		||||
                    </th>
 | 
			
		||||
                    <th class="text-center">{% trans 'Node' %}</th>
 | 
			
		||||
                    <th class="text-center">{% trans 'User group' %}</th>
 | 
			
		||||
                    <th class="text-center">{% trans 'System user' %}</th>
 | 
			
		||||
                    <th class="text-center">{% trans 'Is active' %}</th>
 | 
			
		||||
                    <th class="text-center">{% trans 'Date expired' %}</th>
 | 
			
		||||
                    <th class="text-center">{% trans 'Action' %}</th>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                  </thead>
 | 
			
		||||
                  <tbody>
 | 
			
		||||
                  </tbody>
 | 
			
		||||
              </table>
 | 
			
		||||
          </div>
 | 
			
		||||
       </div>
 | 
			
		||||
   </div>
 | 
			
		||||
</div>
 | 
			
		||||
<table class="table table-striped table-bordered table-hover" id="permission_list_table" >
 | 
			
		||||
    <thead>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <th class="text-center">
 | 
			
		||||
            <input type="checkbox" id="check_all" class="ipt_check_all" >
 | 
			
		||||
      </th>
 | 
			
		||||
      <th class="text-center">{% trans 'Node' %}</th>
 | 
			
		||||
      <th class="text-center">{% trans 'User group' %}</th>
 | 
			
		||||
      <th class="text-center">{% trans 'System user' %}</th>
 | 
			
		||||
      <th class="text-center">{% trans 'Is active' %}</th>
 | 
			
		||||
      <th class="text-center">{% trans 'Date expired' %}</th>
 | 
			
		||||
      <th class="text-center">{% trans 'Action' %}</th>
 | 
			
		||||
    </tr>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tbody>
 | 
			
		||||
    </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block custom_foot_js %}
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
var zTree, rMenu, table;
 | 
			
		||||
function initTable() {
 | 
			
		||||
    var options = {
 | 
			
		||||
        ele: $('#permission_list_table'),
 | 
			
		||||
        columnDefs: [
 | 
			
		||||
            {targets: 1, createdCell: function (td, cellData) {
 | 
			
		||||
                var html = '<a href="">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html)
 | 
			
		||||
                var html = '<a href="{% url 'assets:tree-view' %}?node=99899">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html.replace("99899", cellData.pk));
 | 
			
		||||
            }},
 | 
			
		||||
            {targets: 2, createdCell: function (td, cellData) {
 | 
			
		||||
                var html = '<a href="">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html)
 | 
			
		||||
                var html = '<a href="{% url "users:user-group-detail" pk=DEFAULT_PK %}">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html.replace("{{ DEFAULT_PK }}", cellData.pk))
 | 
			
		||||
            }},
 | 
			
		||||
            {targets: 3, createdCell: function (td, cellData) {
 | 
			
		||||
                var html = '<a href="">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html)
 | 
			
		||||
                var html = '<a href="{% url 'assets:system-user-detail' pk=DEFAULT_PK %}">' + cellData.name + '</a>';
 | 
			
		||||
                $(td).html(html.replace("{{ DEFAULT_PK }}", cellData.pk));
 | 
			
		||||
            }},
 | 
			
		||||
            {targets: 4, createdCell: function (td, cellData) {
 | 
			
		||||
                if (!cellData) {
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +103,14 @@ function initTable() {
 | 
			
		|||
					$(td).html('<i class="fa fa-check text-navy"></i>')
 | 
			
		||||
				}
 | 
			
		||||
            }},
 | 
			
		||||
 | 
			
		||||
            {targets: 5, createdCell: function (td, cellData) {
 | 
			
		||||
                var date_expired = cellData.split(" ");
 | 
			
		||||
                if (date_expired && date_expired.length === 3) {
 | 
			
		||||
                    $(td).html(date_expired[0]);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $(td).html(cellData);
 | 
			
		||||
                }
 | 
			
		||||
            }},
 | 
			
		||||
            {targets: 6, createdCell: function (td, cellData, rowData) {
 | 
			
		||||
                var update_btn = '<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
 | 
			
		||||
                var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
 | 
			
		||||
| 
						 | 
				
			
			@ -76,13 +127,75 @@ function initTable() {
 | 
			
		|||
        ],
 | 
			
		||||
        op_html: $('#actions').html()
 | 
			
		||||
    };
 | 
			
		||||
    jumpserver.initDataTable(options)
 | 
			
		||||
    table = jumpserver.initDataTable(options);
 | 
			
		||||
    return table
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function onSelected(event, treeNode) {
 | 
			
		||||
    var url = table.ajax.url();
 | 
			
		||||
    url = setUrlParam(url, "node_id", treeNode.id);
 | 
			
		||||
    table.ajax.url(url);
 | 
			
		||||
    table.ajax.reload();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function selectQueryNode() {
 | 
			
		||||
    var node_id = $.getUrlParam("node");
 | 
			
		||||
    if (node_id !== null) {
 | 
			
		||||
        var node = zTree.getNodesByParam("id", node_id, null);
 | 
			
		||||
        if (node) {
 | 
			
		||||
            zTree.selectNode(node[0]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initTree() {
 | 
			
		||||
    var setting = {
 | 
			
		||||
        view: {
 | 
			
		||||
            dblClickExpand: false,
 | 
			
		||||
            showLine: true
 | 
			
		||||
        },
 | 
			
		||||
        data: {
 | 
			
		||||
            simpleData: {
 | 
			
		||||
                enable: true
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        callback: {
 | 
			
		||||
            onSelected: onSelected
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    var zNodes = [];
 | 
			
		||||
    $.get("{% url 'api-assets:node-list' %}", function(data, status){
 | 
			
		||||
        $.each(data, function (index, value) {
 | 
			
		||||
            value["pId"] = value["parent"];
 | 
			
		||||
            if (value["key"] === "0") {
 | 
			
		||||
                value["open"] = true;
 | 
			
		||||
            }
 | 
			
		||||
            value["name"] = value["value"]
 | 
			
		||||
        });
 | 
			
		||||
        zNodes = data;
 | 
			
		||||
        $.fn.zTree.init($("#assetTree"), setting, zNodes);
 | 
			
		||||
        zTree = $.fn.zTree.getZTreeObj("assetTree");
 | 
			
		||||
		rMenu = $("#rMenu");
 | 
			
		||||
		selectQueryNode();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$(document).ready(function(){
 | 
			
		||||
    initTable()
 | 
			
		||||
    initTable();
 | 
			
		||||
    initTree();
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.btn-create-asset', function () {
 | 
			
		||||
    var url = "{% url 'assets:asset-create' %}";
 | 
			
		||||
    var nodes = zTree.getSelectedNodes();
 | 
			
		||||
    var current_node;
 | 
			
		||||
    if (nodes && nodes.length ===1 ){
 | 
			
		||||
        current_node = nodes[0];
 | 
			
		||||
        url += "?node=" + current_node.id;
 | 
			
		||||
    }
 | 
			
		||||
    window.open(url);
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
.on('click', '.btn-del', function () {
 | 
			
		||||
    var $this = $(this);
 | 
			
		||||
    var name = $this.data('name');
 | 
			
		||||
| 
						 | 
				
			
			@ -91,5 +204,16 @@ $(document).ready(function(){
 | 
			
		|||
            .replace('{{ DEFAULT_PK }}', uid);
 | 
			
		||||
    objectDelete($this, name, the_url);
 | 
			
		||||
})
 | 
			
		||||
.on('click', '.btn-create-permission', function () {
 | 
			
		||||
    var url = "{% url 'perms:asset-permission-create' %}";
 | 
			
		||||
    var nodes = zTree.getSelectedNodes();
 | 
			
		||||
    var current_node;
 | 
			
		||||
    if (nodes && nodes.length ===1 ){
 | 
			
		||||
        current_node = nodes[0];
 | 
			
		||||
        url += "?node_id=" + current_node.id;
 | 
			
		||||
    }
 | 
			
		||||
    window.open(url);
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,9 @@ from django.urls import reverse_lazy
 | 
			
		|||
from django.contrib.messages.views import SuccessMessageMixin
 | 
			
		||||
from django.views.generic.detail import DetailView, SingleObjectMixin
 | 
			
		||||
 | 
			
		||||
from common.const import create_success_msg, update_success_msg
 | 
			
		||||
from common.utils import get_object_or_none
 | 
			
		||||
from .hands import AdminUserRequiredMixin, User, UserGroup, SystemUser, \
 | 
			
		||||
    Asset, AssetGroup
 | 
			
		||||
    Asset, AssetGroup, Node
 | 
			
		||||
from .models import AssetPermission, NodePermission
 | 
			
		||||
from .forms import AssetPermissionForm
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +37,15 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
 | 
			
		|||
    template_name = 'perms/asset_permission_create_update.html'
 | 
			
		||||
    success_url = reverse_lazy('perms:asset-permission-list')
 | 
			
		||||
 | 
			
		||||
    def get_form(self, form_class=None):
 | 
			
		||||
        form = super().get_form(form_class=form_class)
 | 
			
		||||
        node_id = self.request.GET.get("node_id")
 | 
			
		||||
        node = get_object_or_none(Node, id=node_id)
 | 
			
		||||
        if not node:
 | 
			
		||||
            node = Node.root()
 | 
			
		||||
        form['node'].initial = node
 | 
			
		||||
        return form
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
            'app': _('Perms'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -530,4 +530,44 @@ function createPopover(dataset, title, callback) {
 | 
			
		|||
 | 
			
		||||
    var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>";
 | 
			
		||||
    return html;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 $(function () {
 | 
			
		||||
    (function ($) {
 | 
			
		||||
        $.getUrlParam = function (name) {
 | 
			
		||||
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
 | 
			
		||||
            var r = window.location.search.substr(1).match(reg);
 | 
			
		||||
            if (r != null) return unescape(r[2]); return null;
 | 
			
		||||
        }
 | 
			
		||||
    })(jQuery);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function getUrlParam(name) {
 | 
			
		||||
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
 | 
			
		||||
    var r = window.location.search.substr(1).match(reg);
 | 
			
		||||
    if (r != null) return unescape(r[2]); return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setUrlParam(url, name, value) {
 | 
			
		||||
    var urlArray = url.split("?");
 | 
			
		||||
    if (urlArray.length===1){
 | 
			
		||||
        url += "?" + name + "=" + value;
 | 
			
		||||
    } else {
 | 
			
		||||
        var oriParam = urlArray[1].split("&");
 | 
			
		||||
        var oriParamMap = {};
 | 
			
		||||
        $.each(oriParam, function (index, value) {
 | 
			
		||||
            var v = value.split("=");
 | 
			
		||||
            oriParamMap[v[0]] = v[1];
 | 
			
		||||
        });
 | 
			
		||||
        oriParamMap[name] = value;
 | 
			
		||||
        url = urlArray[0] + "?";
 | 
			
		||||
        var newParam = [];
 | 
			
		||||
        $.each(oriParamMap, function (index, value) {
 | 
			
		||||
            console.log(index, value);
 | 
			
		||||
            newParam.push(index + "=" + value);
 | 
			
		||||
        });
 | 
			
		||||
        url += newParam.join("&")
 | 
			
		||||
    }
 | 
			
		||||
    return url
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,6 @@
 | 
			
		|||
    </a>
 | 
			
		||||
    <ul class="nav nav-second-level">
 | 
			
		||||
        <li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
 | 
			
		||||
        <li id="asset-group"><a href="{% url 'assets:asset-group-list' %}">{% trans 'Asset group' %}</a></li>
 | 
			
		||||
        <li id="cluster"><a href="{% url 'assets:cluster-list' %}">{% trans 'Cluster' %}</a></li>
 | 
			
		||||
        <li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li>
 | 
			
		||||
        <li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li>
 | 
			
		||||
        <li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,14 +17,14 @@ from .models import User, UserGroup
 | 
			
		|||
from .permissions import IsSuperUser, IsValidUser, IsCurrentUserOrReadOnly, \
 | 
			
		||||
    IsSuperUserOrAppUser
 | 
			
		||||
from .utils import check_user_valid, generate_token
 | 
			
		||||
from common.mixins import CustomFilterMixin
 | 
			
		||||
from common.mixins import IDInFilterMixin
 | 
			
		||||
from common.utils import get_logger
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
logger = get_logger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserViewSet(CustomFilterMixin, BulkModelViewSet):
 | 
			
		||||
class UserViewSet(IDInFilterMixin, BulkModelViewSet):
 | 
			
		||||
    queryset = User.objects.exclude(role="App")
 | 
			
		||||
    # queryset = User.objects.all().exclude(role="App").order_by("date_joined")
 | 
			
		||||
    serializer_class = UserSerializer
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ class UserUpdatePKApi(generics.UpdateAPIView):
 | 
			
		|||
        user.save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserGroupViewSet(CustomFilterMixin, BulkModelViewSet):
 | 
			
		||||
class UserGroupViewSet(IDInFilterMixin, BulkModelViewSet):
 | 
			
		||||
    queryset = UserGroup.objects.all()
 | 
			
		||||
    serializer_class = UserGroupSerializer
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue