mirror of https://github.com/jumpserver/jumpserver
[Update] 优化授权规则资产列表页面 (#2937)
* [Update] 优化授权规则资产列表页面 * [Update] 优化授权规则资产列表页面2 * [Update] 优化授权规则资产列表页面3 * [Update] 优化授权规则资产列表页面4 * [Update] 优化授权规则资产列表页面5 * [Update] 优化授权规则资产列表页面6pull/2942/head
parent
7bda48bd9f
commit
e5bdceed58
|
@ -4,7 +4,8 @@
|
|||
from django.utils import timezone
|
||||
from django.db.models import Q
|
||||
from rest_framework.views import Response
|
||||
from rest_framework.generics import RetrieveUpdateAPIView
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.generics import RetrieveUpdateAPIView, ListAPIView
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.pagination import LimitOffsetPagination
|
||||
|
||||
|
@ -20,7 +21,7 @@ from .. import serializers
|
|||
__all__ = [
|
||||
'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi',
|
||||
'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi',
|
||||
'AssetPermissionAddAssetApi',
|
||||
'AssetPermissionAddAssetApi', 'AssetPermissionAssetsApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -232,3 +233,22 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
|
|||
return Response({"msg": "ok"})
|
||||
else:
|
||||
return Response({"error": serializer.errors})
|
||||
|
||||
|
||||
class AssetPermissionAssetsApi(ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
pagination_class = LimitOffsetPagination
|
||||
serializer_class = serializers.AssetPermissionAssetsSerializer
|
||||
filter_fields = ("hostname", "ip")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_object(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
return get_object_or_404(AssetPermission, pk=pk)
|
||||
|
||||
def get_queryset(self):
|
||||
perm = self.get_object()
|
||||
assets = perm.get_all_assets().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return assets
|
||||
|
|
|
@ -2,6 +2,7 @@ import uuid
|
|||
from functools import reduce
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import date_expired_default, set_or_append_attr_bulk
|
||||
|
@ -93,11 +94,16 @@ class AssetPermission(BasePermission):
|
|||
)
|
||||
|
||||
def get_all_assets(self):
|
||||
assets = set(self.assets.all())
|
||||
for node in self.nodes.all():
|
||||
_assets = node.get_all_assets()
|
||||
set_or_append_attr_bulk(_assets, 'inherit', node.value)
|
||||
assets.update(set(_assets))
|
||||
args = [Q(granted_by_permissions=self)]
|
||||
pattern = set()
|
||||
nodes_keys = self.nodes.all().values_list('key', flat=True)
|
||||
for key in nodes_keys:
|
||||
pattern.add(r'^{0}$|^{0}:'.format(key))
|
||||
pattern = '|'.join(list(pattern))
|
||||
if pattern:
|
||||
args.append(Q(nodes__key__regex=pattern))
|
||||
args = reduce(lambda x, y: x | y, args)
|
||||
assets = Asset.objects.filter(args)
|
||||
return assets
|
||||
|
||||
|
||||
|
|
|
@ -6,11 +6,12 @@ from rest_framework import serializers
|
|||
from common.fields import StringManyToManyField
|
||||
from orgs.mixins import BulkOrgResourceModelSerializer
|
||||
from perms.models import AssetPermission, Action
|
||||
from assets.models import Asset
|
||||
|
||||
__all__ = [
|
||||
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
|
||||
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
|
||||
'ActionsField',
|
||||
'ActionsField', 'AssetPermissionAssetsSerializer',
|
||||
]
|
||||
|
||||
|
||||
|
@ -70,3 +71,11 @@ class AssetPermissionUpdateAssetSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = AssetPermission
|
||||
fields = ['id', 'assets']
|
||||
|
||||
|
||||
class AssetPermissionAssetsSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
only_fields = ['id', 'hostname', 'ip']
|
||||
fields = tuple(only_fields)
|
||||
|
|
|
@ -48,29 +48,19 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<table class="table table-hover">
|
||||
<table class="table table-striped table-bordered table-hover" id="asset_list_table" style="width: 100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'Hostname' %}</th>
|
||||
<th>{% trans 'IP' %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input type="checkbox" id="check_all" class="ipt_check_all" >
|
||||
</th>
|
||||
<th class="text-center">{% trans 'Hostname' %}</th>
|
||||
<th class="text-center">{% trans 'IP' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for asset in object_list %}
|
||||
<tr>
|
||||
<td>{{ asset.hostname }}</td>
|
||||
<td>{{ asset.ip }}</td>
|
||||
<td>
|
||||
<button title="{{ asset.inherit }}" data-gid="{{ asset.id }}" class="btn btn-danger btn-xs btn-remove-asset {% if asset.inherit %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
{% include '_pagination.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -86,9 +76,6 @@
|
|||
<tr class="no-borders-tr">
|
||||
<td colspan="2">
|
||||
<select data-placeholder="{% trans 'Select assets' %}" class="select2" id="asset_select2" style="width: 100%" multiple="" tabindex="4">
|
||||
{% for asset in assets_remain %}
|
||||
<option value="{{ asset.id }}">{{ asset }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -146,6 +133,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'assets/_asset_list_modal.html' %}
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
|
@ -162,7 +150,7 @@ function addAssets(assets) {
|
|||
body: JSON.stringify(body),
|
||||
success: success
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function removeAssets(assets) {
|
||||
var the_url = "{% url 'api-perms:asset-permission-remove-asset' pk=asset_permission.id %}";
|
||||
|
@ -191,9 +179,57 @@ function updateNodes(nodes, success) {
|
|||
});
|
||||
}
|
||||
|
||||
var table;
|
||||
function initAssetTable() {
|
||||
var options = {
|
||||
ele: $('#asset_list_table'),
|
||||
toggle: true,
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0, createdCell: function (td, cellData, rowData) {
|
||||
var html = '<input type="checkbox" class="text-center ipt_check" id="id_' + cellData + '">';
|
||||
$(td).html(html);
|
||||
}
|
||||
},
|
||||
],
|
||||
ajax_url: "{% url 'api-perms:asset-permission-assets' pk=object.id %}",
|
||||
columns: [
|
||||
{data: "id"}, {data: "hostname"}, {data: "ip"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
table = jumpserver.initServerSideDataTable(options);
|
||||
return table
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
$('.select2').select2();
|
||||
table = initAssetTable();
|
||||
$("#asset_select2").parent().find(".select2-selection").on('click', function (e) {
|
||||
if ($(e.target).attr('class') !== 'select2-selection__choice__remove'){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$("#asset_list_modal").modal();
|
||||
initSelectedAssets2Table('#asset_select2');
|
||||
}
|
||||
})
|
||||
})
|
||||
.on('click', '#btn_asset_modal_confirm', function () {
|
||||
var assets = asset_table2.selected;
|
||||
var options = [];
|
||||
$('#asset_select2 option').each(function (i, v) {
|
||||
options.push(v.value)
|
||||
});
|
||||
asset_table2.selected_rows.forEach(function (i) {
|
||||
var name = i.hostname + '(' + i.ip + ')';
|
||||
var option = new Option(name, i.id, false, true);
|
||||
|
||||
if (options.indexOf(i.id) === -1) {
|
||||
$('#asset_select2').append(option).trigger('change');
|
||||
}
|
||||
});
|
||||
$('#asset_select2').val(assets).trigger('change');
|
||||
$("#asset_list_modal").modal('hide');
|
||||
})
|
||||
.on('click', '.btn-add-assets', function () {
|
||||
var assets_selected = $("#asset_select2 option:selected").map(function () {
|
||||
|
@ -237,7 +273,7 @@ $(document).ready(function () {
|
|||
});
|
||||
};
|
||||
updateNodes(nodes, success);
|
||||
})
|
||||
})
|
||||
.on('click', '.btn-remove-node', function () {
|
||||
var $this = $(this);
|
||||
var $tr = $this.closest('tr');
|
||||
|
|
|
@ -50,6 +50,9 @@ asset_permission_urlpatterns = [
|
|||
path('asset-permissions/<uuid:pk>/asset/remove/', api.AssetPermissionRemoveAssetApi.as_view(), name='asset-permission-remove-asset'),
|
||||
path('asset-permissions/<uuid:pk>/asset/add/', api.AssetPermissionAddAssetApi.as_view(), name='asset-permission-add-asset'),
|
||||
|
||||
# 授权规则中授权的资产
|
||||
path('asset-permissions/<uuid:pk>/assets/', api.AssetPermissionAssetsApi.as_view(), name='asset-permission-assets'),
|
||||
|
||||
# 验证用户是否有某个资产和系统用户的权限
|
||||
path('asset-permissions/user/validate/', api.ValidateUserAssetPermissionApi.as_view(), name='validate-user-asset-permission'),
|
||||
path('asset-permissions/user/actions/', api.GetUserAssetPermissionActionsApi.as_view(), name='get-user-asset-permission-actions'),
|
||||
|
|
|
@ -163,12 +163,12 @@ class AssetPermissionAssetView(PermissionsMixin,
|
|||
return queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
assets_granted = self.get_queryset()
|
||||
granted_nodes = self.object.nodes.all()
|
||||
nodes_remain = [n for n in Node.get_queryset() if n not in granted_nodes]
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('Asset permission asset list'),
|
||||
'assets_remain': Asset.objects.exclude(id__in=[a.id for a in assets_granted]),
|
||||
'nodes_remain': Node.objects.exclude(granted_by_permissions=self.object),
|
||||
'nodes_remain': nodes_remain,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
Loading…
Reference in New Issue