提交 2d396787 编写于 作者: baltery's avatar baltery

[Feature] 完成资产授权和资产添加

上级 653c328e
......@@ -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 () {
......
......@@ -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
......
{% extends '_base_list.html' %}
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block table_search %}
{% endblock %}
{% 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>
{% 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;
}
\ No newline at end of file
}
$(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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册