Commit e5bdceed authored by BaiJiangJie's avatar BaiJiangJie Committed by 老广

[Update] 优化授权规则资产列表页面 (#2937)

* [Update] 优化授权规则资产列表页面

* [Update] 优化授权规则资产列表页面2

* [Update] 优化授权规则资产列表页面3

* [Update] 优化授权规则资产列表页面4

* [Update] 优化授权规则资产列表页面5

* [Update] 优化授权规则资产列表页面6
parent 7bda48bd
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
from django.utils import timezone from django.utils import timezone
from django.db.models import Q from django.db.models import Q
from rest_framework.views import Response 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 import viewsets
from rest_framework.pagination import LimitOffsetPagination from rest_framework.pagination import LimitOffsetPagination
...@@ -20,7 +21,7 @@ from .. import serializers ...@@ -20,7 +21,7 @@ from .. import serializers
__all__ = [ __all__ = [
'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi', 'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi',
'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi', 'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi',
'AssetPermissionAddAssetApi', 'AssetPermissionAddAssetApi', 'AssetPermissionAssetsApi',
] ]
...@@ -232,3 +233,22 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView): ...@@ -232,3 +233,22 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
return Response({"msg": "ok"}) return Response({"msg": "ok"})
else: else:
return Response({"error": serializer.errors}) 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 ...@@ -2,6 +2,7 @@ import uuid
from functools import reduce from functools import reduce
from django.db import models from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import date_expired_default, set_or_append_attr_bulk from common.utils import date_expired_default, set_or_append_attr_bulk
...@@ -93,11 +94,16 @@ class AssetPermission(BasePermission): ...@@ -93,11 +94,16 @@ class AssetPermission(BasePermission):
) )
def get_all_assets(self): def get_all_assets(self):
assets = set(self.assets.all()) args = [Q(granted_by_permissions=self)]
for node in self.nodes.all(): pattern = set()
_assets = node.get_all_assets() nodes_keys = self.nodes.all().values_list('key', flat=True)
set_or_append_attr_bulk(_assets, 'inherit', node.value) for key in nodes_keys:
assets.update(set(_assets)) 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 return assets
......
...@@ -6,11 +6,12 @@ from rest_framework import serializers ...@@ -6,11 +6,12 @@ from rest_framework import serializers
from common.fields import StringManyToManyField from common.fields import StringManyToManyField
from orgs.mixins import BulkOrgResourceModelSerializer from orgs.mixins import BulkOrgResourceModelSerializer
from perms.models import AssetPermission, Action from perms.models import AssetPermission, Action
from assets.models import Asset
__all__ = [ __all__ = [
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer', 'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer', 'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
'ActionsField', 'ActionsField', 'AssetPermissionAssetsSerializer',
] ]
...@@ -70,3 +71,11 @@ class AssetPermissionUpdateAssetSerializer(serializers.ModelSerializer): ...@@ -70,3 +71,11 @@ class AssetPermissionUpdateAssetSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = AssetPermission model = AssetPermission
fields = ['id', 'assets'] fields = ['id', 'assets']
class AssetPermissionAssetsSerializer(serializers.ModelSerializer):
class Meta:
model = Asset
only_fields = ['id', 'hostname', 'ip']
fields = tuple(only_fields)
...@@ -48,29 +48,19 @@ ...@@ -48,29 +48,19 @@
</div> </div>
</div> </div>
<div class="ibox-content"> <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> <thead>
<tr> <tr>
<th>{% trans 'Hostname' %}</th> <th class="text-center">
<th>{% trans 'IP' %}</th> <input type="checkbox" id="check_all" class="ipt_check_all" >
<th></th> </th>
</tr> <th class="text-center">{% trans 'Hostname' %}</th>
<th class="text-center">{% trans 'IP' %}</th>
</tr>
</thead> </thead>
<tbody> <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> </tbody>
</table> </table>
<div class="row">
{% include '_pagination.html' %}
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -86,9 +76,6 @@ ...@@ -86,9 +76,6 @@
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select assets' %}" class="select2" id="asset_select2" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select assets' %}" class="select2" id="asset_select2" style="width: 100%" multiple="" tabindex="4">
{% for asset in assets_remain %}
<option value="{{ asset.id }}">{{ asset }}</option>
{% endfor %}
</select> </select>
</td> </td>
</tr> </tr>
...@@ -146,6 +133,7 @@ ...@@ -146,6 +133,7 @@
</div> </div>
</div> </div>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
...@@ -162,7 +150,7 @@ function addAssets(assets) { ...@@ -162,7 +150,7 @@ function addAssets(assets) {
body: JSON.stringify(body), body: JSON.stringify(body),
success: success success: success
}); });
} }
function removeAssets(assets) { function removeAssets(assets) {
var the_url = "{% url 'api-perms:asset-permission-remove-asset' pk=asset_permission.id %}"; var the_url = "{% url 'api-perms:asset-permission-remove-asset' pk=asset_permission.id %}";
...@@ -191,9 +179,57 @@ function updateNodes(nodes, success) { ...@@ -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 () { $(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 () { .on('click', '.btn-add-assets', function () {
var assets_selected = $("#asset_select2 option:selected").map(function () { var assets_selected = $("#asset_select2 option:selected").map(function () {
...@@ -237,7 +273,7 @@ $(document).ready(function () { ...@@ -237,7 +273,7 @@ $(document).ready(function () {
}); });
}; };
updateNodes(nodes, success); updateNodes(nodes, success);
}) })
.on('click', '.btn-remove-node', function () { .on('click', '.btn-remove-node', function () {
var $this = $(this); var $this = $(this);
var $tr = $this.closest('tr'); var $tr = $this.closest('tr');
......
...@@ -50,6 +50,9 @@ asset_permission_urlpatterns = [ ...@@ -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/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>/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/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'), path('asset-permissions/user/actions/', api.GetUserAssetPermissionActionsApi.as_view(), name='get-user-asset-permission-actions'),
......
...@@ -163,12 +163,12 @@ class AssetPermissionAssetView(PermissionsMixin, ...@@ -163,12 +163,12 @@ class AssetPermissionAssetView(PermissionsMixin,
return queryset return queryset
def get_context_data(self, **kwargs): 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 = { context = {
'app': _('Perms'), 'app': _('Perms'),
'action': _('Asset permission asset list'), 'action': _('Asset permission asset list'),
'assets_remain': Asset.objects.exclude(id__in=[a.id for a in assets_granted]), 'nodes_remain': nodes_remain,
'nodes_remain': Node.objects.exclude(granted_by_permissions=self.object),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment