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