Commit 8e9b3f13 authored by ibuler's avatar ibuler

[Update] 修改permission actions

parents 48ba1993 320b17c8
......@@ -112,12 +112,16 @@ class NodeChildrenAsTreeApi(generics.ListAPIView):
is_root = False
def get_queryset(self):
self.check_need_refresh_nodes()
node_key = self.request.query_params.get('key')
util = NodeUtil()
# 是否包含自己
with_self = False
if not node_key:
node_key = Node.root().key
with_self = True
self.node = util.get_node_by_key(node_key)
queryset = self.node.get_children(with_self=True)
queryset = self.node.get_children(with_self=with_self)
queryset = [node.as_tree_node() for node in queryset]
queryset = sorted(queryset)
return queryset
......@@ -133,14 +137,11 @@ class NodeChildrenAsTreeApi(generics.ListAPIView):
def filter_queryset(self, queryset):
queryset = self.filter_assets(queryset)
queryset = self.filter_refresh_nodes(queryset)
return queryset
def filter_refresh_nodes(self, queryset):
def check_need_refresh_nodes(self):
if self.request.query_params.get('refresh', '0') == '1':
Node.expire_nodes_assets_amount()
Node.expire_nodes_full_value()
return queryset
Node.refresh_nodes()
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
......
......@@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _
from common.utils import get_logger
from orgs.mixins import OrgModelForm
from ..models import Asset, Protocol
from ..models import Asset, Protocol, Node
logger = get_logger(__file__)
......@@ -33,6 +33,12 @@ class ProtocolForm(forms.ModelForm):
class AssetCreateForm(OrgModelForm):
PROTOCOL_CHOICES = Protocol.PROTOCOL_CHOICES
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.data:
nodes_field = self.fields['nodes']
nodes_field._queryset = Node.get_queryset()
class Meta:
model = Asset
fields = [
......
......@@ -186,9 +186,6 @@ class FullValueMixin:
def expire_nodes_full_value(cls, nodes=None):
key = cls._full_value_cache_key.format('*')
cache.delete_pattern(key+'*')
from ..utils import NodeUtil
util = NodeUtil()
util.set_full_value()
class AssetsAmountMixin:
......@@ -216,7 +213,7 @@ class AssetsAmountMixin:
def assets_amount(self, value):
self._assets_amount = value
cache_key = self._assets_amount_cache_key.format(self.key)
cache.set(cache_key, value, 3600 * 24)
cache.set(cache_key, value)
def expire_assets_amount(self):
ancestor_keys = self.get_ancestor_keys(with_self=True)
......@@ -226,11 +223,15 @@ class AssetsAmountMixin:
@classmethod
def expire_nodes_assets_amount(cls, nodes=None):
from ..utils import NodeUtil
key = cls._assets_amount_cache_key.format('*')
cache.delete_pattern(key)
@classmethod
def refresh_nodes(cls):
from ..utils import NodeUtil
util = NodeUtil(with_assets_amount=True)
util.set_assets_amount()
util.set_full_value()
class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
......@@ -375,9 +376,7 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
def as_tree_node(self):
from common.tree import TreeNode
from ..serializers import NodeSerializer
name = '{} ({})'.format(self.value, self.assets_amount)
node_serializer = NodeSerializer(instance=self)
data = {
'id': self.key,
'name': name,
......@@ -386,7 +385,12 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
'isParent': True,
'open': self.is_root(),
'meta': {
'node': node_serializer.data,
'node': {
"id": self.id,
"name": self.name,
"value": self.value,
"key": self.key,
},
'type': 'node'
}
}
......
# -*- coding: utf-8 -*-
from rest_framework import serializers
from django.utils.translation import ugettext as _
from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import Asset, Node
......@@ -25,11 +26,11 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
def validate_value(self, data):
instance = self.instance if self.instance else Node.root()
children = instance.parent.get_children().exclude(key=instance.key)
values = [child.value for child in children]
if data in values:
children = instance.parent.get_children()
children_values = [node.value for node in children if node != instance]
if data in children_values:
raise serializers.ValidationError(
'The same level node name cannot be the same'
_('The same level node name cannot be the same')
)
return data
......
......@@ -67,6 +67,7 @@ function initTable2() {
columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" }
],
lengthMenu: [[10, 25, 50], [10, 25, 50]],
pageLength: 10
};
asset_table2 = jumpserver.initServerSideDataTable(options);
......
This diff is collapsed.
# ~*~ coding: utf-8 ~*~
#
import time
from django.db.models import Prefetch
from common.utils import get_object_or_none, get_logger
......@@ -56,9 +57,11 @@ class NodeUtil:
def get_all_nodes(self):
all_nodes = Node.objects.all()
if self.with_assets_amount:
now = time.time()
all_nodes = all_nodes.prefetch_related(
Prefetch('assets', queryset=Asset.objects.all().only('id'))
)
all_nodes = list(all_nodes)
for node in all_nodes:
node._assets = set(node.assets.all())
all_nodes = sorted(all_nodes, key=self.sorted_by)
......
......@@ -130,16 +130,13 @@ def get_short_uuid_str():
def is_uuid(seq):
if isinstance(seq, str):
if UUID_PATTERN.match(seq):
return True
else:
return False
else:
for s in seq:
if not is_uuid(s):
return False
if isinstance(seq, uuid.UUID):
return True
elif isinstance(seq, str) and UUID_PATTERN.match(seq):
return True
elif isinstance(seq, (list, tuple)):
all([is_uuid(x) for x in seq])
return False
def get_request_ip(request):
......
......@@ -399,7 +399,7 @@ REST_FRAMEWORK = {
'ORDERING_PARAM': "order",
'SEARCH_PARAM': "search",
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S %z',
'DATETIME_INPUT_FORMATS': ['%Y-%m-%d %H:%M:%S %z'],
'DATETIME_INPUT_FORMATS': ['iso-8601', '%Y-%m-%d %H:%M:%S %z'],
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
# 'PAGE_SIZE': 15
}
......
This diff is collapsed.
# -*- coding: utf-8 -*-
#
from assets.models import Node
from orgs.utils import set_current_org, current_org
from orgs.utils import set_current_org, current_org, get_current_org
......@@ -4,7 +4,8 @@ import traceback
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import redirect, get_object_or_404
from django.forms import ModelForm
from django import forms
from django.core.exceptions import ValidationError
from django.http.response import HttpResponseForbidden
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
......@@ -101,6 +102,26 @@ class OrgModelMixin(models.Model):
else:
return name
def validate_unique(self, exclude=None):
"""
Check unique constraints on the model and raise ValidationError if any
failed.
Form 提交时会使用这个检验
"""
self.org_id = current_org.id if current_org.is_real() else ''
if exclude and 'org_id' in exclude:
exclude.remove('org_id')
unique_checks, date_checks = self._get_unique_checks(exclude=exclude)
errors = self._perform_unique_checks(unique_checks)
date_errors = self._perform_date_checks(date_checks)
for k, v in date_errors.items():
errors.setdefault(k, []).extend(v)
if errors:
raise ValidationError(errors)
class Meta:
abstract = True
......@@ -123,11 +144,9 @@ class RootOrgViewMixin:
return super().dispatch(request, *args, **kwargs)
class OrgModelForm(ModelForm):
class OrgModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# if 'initial' not in kwargs:
# return
for name, field in self.fields.items():
if not hasattr(field, 'queryset'):
continue
......
......@@ -6,7 +6,7 @@ from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Organization
from .hands import set_current_org, current_org, Node
from .hands import set_current_org, current_org, Node, get_current_org
from perms.models import AssetPermission
from users.models import UserGroup
......@@ -14,7 +14,7 @@ from users.models import UserGroup
@receiver(post_save, sender=Organization)
def on_org_create_or_update(sender, instance=None, created=False, **kwargs):
if instance:
old_org = current_org
old_org = get_current_org()
set_current_org(instance)
node_root = Node.root()
if node_root.value != instance.name:
......
......@@ -20,16 +20,10 @@ from .. import serializers
__all__ = [
'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi',
'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi',
'AssetPermissionAddAssetApi', 'ActionViewSet',
'AssetPermissionAddAssetApi',
]
class ActionViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Action.objects.all()
serializer_class = serializers.ActionSerializer
permission_classes = (IsOrgAdmin,)
class AssetPermissionViewSet(viewsets.ModelViewSet):
"""
资产授权列表的增删改查api
......
......@@ -14,7 +14,6 @@ from rest_framework.pagination import LimitOffsetPagination
from common.permissions import IsValidUser, IsOrgAdminOrAppUser
from common.tree import TreeNodeSerializer
from common.utils import get_logger
from orgs.utils import set_to_root_org
from ..utils import (
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node,
check_system_user_action, RemoteAppPermissionUtil,
......@@ -515,6 +514,7 @@ class ValidateUserRemoteAppPermissionApi(APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def get(self, request, *args, **kwargs):
self.change_org_if_need(request, kwargs)
user_id = request.query_params.get('user_id', '')
remote_app_id = request.query_params.get('remote_app_id', '')
user = get_object_or_404(User, id=user_id)
......
# ~*~ coding: utf-8 ~*~
from __future__ import absolute_import, unicode_literals
from functools import reduce
from django import forms
from django.utils.translation import ugettext_lazy as _
......@@ -18,17 +19,22 @@ class AssetPermissionForm(OrgModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'):
users_field.queryset = current_org.get_org_users()
assets_field = self.fields.get('assets')
users_field.queryset = current_org.get_org_users()
# 前端渲染优化, 防止过多资产
if not self.data:
instance = kwargs.get('instance')
assets_field = self.fields['assets']
if instance:
assets_field.queryset = instance.assets.all()
else:
assets_field.queryset = Asset.objects.none()
nodes_field = self.fields['nodes']
nodes_field._queryset = Node.get_queryset()
def clean_action(self):
actions = self.cleaned_data.get("action")
return reduce(lambda x, y: x | y, actions)
class Meta:
model = AssetPermission
......@@ -51,16 +57,14 @@ class AssetPermissionForm(OrgModelForm):
'system_users': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('System user')}
),
'actions': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Action')}
)
'action': forms.CheckboxSelectMultiple()
}
labels = {
'nodes': _("Node"),
}
help_texts = {
'actions': _('Tips: The RDP protocol does not support separate '
'controls for uploading or downloading files')
'action': _('Tips: The RDP protocol does not support separate '
'controls for uploading or downloading files')
}
def clean_user_groups(self):
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-25 10:15
from __future__ import unicode_literals
import common.utils
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('users', '0004_auto_20180125_1218'),
('assets', '0007_auto_20180225_1815'),
('perms', '0002_auto_20171228_0025'),
]
operations = [
migrations.CreateModel(
name='NodePermission',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('date_expired', models.DateTimeField(default=common.utils.date_expired_default, verbose_name='Date expired')),
('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('node', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Node', verbose_name='Node')),
('system_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser', verbose_name='System user')),
('user_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.UserGroup', verbose_name='User group')),
],
options={
'verbose_name': 'Asset permission',
},
),
migrations.AlterUniqueTogether(
name='nodepermission',
unique_together=set([('node', 'user_group', 'system_user')]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-04-11 03:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('assets', '0013_auto_20180411_1135'),
('perms', '0003_auto_20180225_1815'),
]
operations = [
migrations.RemoveField(
model_name='assetpermission',
name='asset_groups',
),
migrations.AddField(
model_name='assetpermission',
name='date_start',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date start'),
),
migrations.AddField(
model_name='assetpermission',
name='nodes',
field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Node', verbose_name='Nodes'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-04-11 03:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
def migrate_node_permissions(apps, schema_editor):
node_perm_model = apps.get_model("perms", "NodePermission")
asset_perm_model = apps.get_model("perms", "AssetPermission")
db_alias = schema_editor.connection.alias
for old in node_perm_model.objects.using(db_alias).all():
perm = asset_perm_model.objects.using(db_alias).create(
name="{}-{}-{}".format(
old.node.value,
old.user_group.name,
old.system_user.name
),
is_active=old.is_active,
date_expired=old.date_expired,
created_by=old.date_expired,
date_created=old.date_created,
comment=old.comment,
)
perm.user_groups.add(old.user_group)
perm.nodes.add(old.node)
perm.system_users.add(old.system_user)
def migrate_system_assets_relation(apps, schema_editor):
system_user_model = apps.get_model("assets", "SystemUser")
db_alias = schema_editor.connection.alias
for s in system_user_model.objects.using(db_alias).all():
nodes = list(s.nodes.all())
s.nodes.set([])
s.nodes.set(nodes)
class Migration(migrations.Migration):
dependencies = [
('perms', '0004_auto_20180411_1135'),
]
operations = [
migrations.RunPython(migrate_node_permissions),
migrations.RunPython(migrate_system_assets_relation),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-06-06 07:05
from __future__ import unicode_literals
import common.utils
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('perms', '0005_migrate_data_20180411_1144'),
]
operations = [
migrations.AlterField(
model_name='assetpermission',
name='date_expired',
field=models.DateTimeField(db_index=True, default=common.utils.date_expired_default, verbose_name='Date expired'),
),
migrations.AlterField(
model_name='assetpermission',
name='date_start',
field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start'),
),
]
# Generated by Django 2.1.7 on 2019-06-28 11:47
from django.db import migrations, models
from functools import reduce
def migrate_old_actions(apps, schema_editor):
from orgs.utils import set_to_root_org
from ..models import ActionFlag
set_to_root_org()
perm_model = apps.get_model('perms', 'AssetPermission')
db_alias = schema_editor.connection.alias
perms = perm_model.objects.using(db_alias).all()
actions_map = {
"all": ActionFlag.ALL,
"connect": ActionFlag.CONNECT,
"upload_file": ActionFlag.UPLOAD,
"download_file": ActionFlag.DOWNLOAD,
}
for perm in perms:
actions = perm.actions.all()
new_actions = [actions_map.get(action.name, ActionFlag.ALL) for action in actions]
new_action = reduce(lambda x, y: x | y, new_actions)
perm.action = new_action
perm.save()
class Migration(migrations.Migration):
dependencies = [
('perms', '0005_auto_20190521_1619'),
]
operations = [
migrations.AddField(
model_name='assetpermission',
name='action',
field=models.IntegerField(
choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'),
(6, 'Upload download'), (4, 'Download file')],
default=255, verbose_name='Action'),
),
migrations.RunPython(migrate_old_actions),
]
# Generated by Django 2.0.7 on 2018-08-07 03:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0006_auto_20180606_1505'),
]
operations = [
migrations.AddField(
model_name='assetpermission',
name='org_id',
field=models.CharField(blank=True, default=None, max_length=36, null=True),
),
migrations.AddField(
model_name='nodepermission',
name='org_id',
field=models.CharField(blank=True, default=None, max_length=36, null=True),
),
migrations.AlterField(
model_name='assetpermission',
name='name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
migrations.AlterUniqueTogether(
name='assetpermission',
unique_together={('org_id', 'name')},
),
migrations.AlterUniqueTogether(
name='nodepermission',
unique_together=set(),
),
]
# Generated by Django 2.1 on 2018-09-03 03:32
# Generated by Django 2.1.7 on 2019-06-28 12:02
from django.db import migrations
......@@ -6,12 +6,12 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('perms', '0008_auto_20180816_1652'),
('perms', '0006_auto_20190628_1921'),
]
operations = [
migrations.AlterModelOptions(
name='assetpermission',
options={'verbose_name': 'Asset permission'},
migrations.RemoveField(
model_name='assetpermission',
name='actions',
),
]
# Generated by Django 2.0.7 on 2018-08-16 08:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0007_auto_20180807_1116'),
]
operations = [
migrations.AlterField(
model_name='assetpermission',
name='org_id',
field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'),
),
migrations.AlterField(
model_name='nodepermission',
name='org_id',
field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'),
),
]
......@@ -11,7 +11,7 @@ from .base import BasePermission
__all__ = [
'Action', 'AssetPermission', 'NodePermission',
'Action', 'AssetPermission', 'NodePermission', 'ActionFlag'
]
......@@ -33,11 +33,28 @@ class Action(models.Model):
return cls.objects.get(name=PERMS_ACTION_NAME_ALL)
class ActionFlag:
CONNECT = 0b00000001
UPLOAD = 0b00000010
DOWNLOAD = 0b00000100
UPDOWNLOAD = CONNECT | DOWNLOAD
ALL = 0b11111111
CHOICES = (
(ALL, _('All')),
(CONNECT, _('Connect')),
(UPLOAD, _('Upload file')),
(UPDOWNLOAD, _("Upload download")),
(DOWNLOAD, _('Download file')),
)
class AssetPermission(BasePermission):
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user"))
actions = models.ManyToManyField('Action', related_name='permissions', blank=True, verbose_name=_('Action'))
# actions = models.ManyToManyField(Action, related_name='permissions', blank=True, verbose_name=_('Action'))
action = models.IntegerField(choices=ActionFlag.CHOICES, default=ActionFlag.ALL, verbose_name=_("Action"))
class Meta:
unique_together = [('org_id', 'name')]
......
......@@ -13,16 +13,10 @@ __all__ = [
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
'ActionSerializer', 'NodeGrantedSerializer',
'NodeGrantedSerializer',
]
class ActionSerializer(serializers.ModelSerializer):
class Meta:
model = Action
fields = '__all__'
class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer):
class Meta:
model = AssetPermission
......@@ -35,7 +29,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
assets = StringManyToManyField(many=True, read_only=True)
nodes = StringManyToManyField(many=True, read_only=True)
system_users = StringManyToManyField(many=True, read_only=True)
actions = StringManyToManyField(many=True, read_only=True)
action = serializers.IntegerField(read_only=True)
is_valid = serializers.BooleanField()
is_expired = serializers.BooleanField()
......
......@@ -25,13 +25,6 @@ def on_transaction_commit(func):
@on_transaction_commit
def on_permission_created(sender, instance=None, created=False, **kwargs):
AssetPermissionUtil.expire_all_cache()
actions = instance.actions.all()
if created and not actions:
default_action = Action.get_action_all()
instance.actions.add(default_action)
logger.debug(
"Set default action to perms: {}".format(default_action, instance)
)
@receiver(post_save, sender=AssetPermission)
......
......@@ -48,7 +48,7 @@
{% bootstrap_field form.system_users layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Action' %}</h3>
{% bootstrap_field form.actions layout="horizontal" %}
{% bootstrap_field form.action layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
<div class="form-group">
......@@ -143,6 +143,34 @@ $(document).ready(function () {
$('#id_assets').val(assets).trigger('change');
$("#asset_list_modal").modal('hide');
});
})
.on("submit", "form", function (evt) {
evt.preventDefault();
var the_url = '{% url 'api-perms:asset-permission-list' %}';
var redirect_to = '{% url "perms:asset-permission-list" %}';
var method = "POST";
var form = $("form");
var data = form.serializeObject();
console.log(data)
var actions = data.action;
var action = 0;
for (i=0;i<actions.length;i++) {
console.log(actions[i])
action |= actions[i];
}
data.action = action;
objectAttrsIsList(data, ['users', 'user_groups', 'system_users', 'nodes', 'assets']);
objectAttrsIsDatetime(data, ['date_start', 'date_expired']);
objectAttrsIsBool(data, ['is_active'])
console.log(data)
var props = {
url: the_url,
data: data,
method: method,
form: form,
redirect_to: redirect_to
};
formSubmit(props);
})
</script>
{% endblock %}
\ No newline at end of file
......@@ -24,15 +24,7 @@
<div class="wrapper wrapper-content">
<div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px">
<div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager ">
<div id="assetTree" class="ztree">
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
{% include 'assets/_node_tree.html' %}
</div>
<div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="tree-toggle">
......@@ -86,7 +78,7 @@
<script>
var zTree, table, show = 0;
function onSelected(event, treeNode) {
function onNodeSelected(event, treeNode) {
setCookie('node_selected', treeNode.id);
var url = table.ajax.url();
if (treeNode.meta.type === 'node') {
......@@ -102,7 +94,7 @@ function onSelected(event, treeNode) {
}
function beforeAsync(treeId, treeNode) {
function beforeNodeAsync(treeId, treeNode) {
if (treeNode) {
return treeNode.meta.type === 'node'
}
......@@ -204,28 +196,12 @@ function initTable() {
function initTree() {
var setting = {
view: {
dblClickExpand: false,
showLine: true
},
data: {
simpleData: {
enable: true
}
},
async: {
enable: true,
url: "{% url 'api-assets:node-children-tree' %}?assets=1",
autoParam:["id=key", "name=n", "level=lv"],
type: 'get'
},
callback: {
onSelected: onSelected,
beforeAsync: beforeAsync
}
};
zTree = $.fn.zTree.init($("#assetTree"), setting);
initNodeTree({
onSelected: onNodeSelected,
beforeAsync: beforeNodeAsync,
showMenu: false,
showAssets: true,
})
}
function toggle() {
......
......@@ -7,7 +7,6 @@ from .. import api
app_name = 'perms'
router = routers.DefaultRouter()
router.register('actions', api.ActionViewSet, 'action')
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission')
......
......@@ -5,6 +5,7 @@ from collections import defaultdict
import json
from hashlib import md5
import time
import itertools
from django.utils import timezone
from django.db.models import Q
......@@ -102,11 +103,11 @@ def get_user_permissions(user, include_group=True):
arg = Q(users=user) | Q(user_groups__in=groups)
else:
arg = Q(users=user)
return AssetPermission.objects.all().valid().filter(arg)
return AssetPermission.objects.valid().filter(arg)
def get_user_group_permissions(user_group):
return AssetPermission.objects.all().valid().filter(
return AssetPermission.objects.valid().filter(
user_groups=user_group
)
......@@ -117,15 +118,15 @@ def get_asset_permissions(asset, include_node=True):
arg = Q(assets=asset) | Q(nodes__in=nodes)
else:
arg = Q(assets=asset)
return AssetPermission.objects.all().valid().filter(arg)
return AssetPermission.objects.valid().filter(arg)
def get_node_permissions(node):
return AssetPermission.objects.all().valid().filter(nodes=node)
return AssetPermission.objects.valid().filter(nodes=node)
def get_system_user_permissions(system_user):
return AssetPermission.objects.valid().all().filter(
return AssetPermission.objects.valid().filter(
system_users=system_user
)
......@@ -141,11 +142,6 @@ def timeit(func):
return wrapper
class AssetGranted:
def __init__(self):
self.system_users = {}
class AssetPermissionCacheMixin:
CACHE_KEY_PREFIX = '_ASSET_PERM_CACHE_'
CACHE_META_KEY_PREFIX = '_ASSET_PERM_META_KEY_'
......@@ -286,6 +282,38 @@ class AssetPermissionCacheMixin:
cache.delete_pattern(key)
class FlatPermissionQueryset:
def __init__(self):
self.queryset = defaultdict(list)
def add(self, permission):
self.queryset[permission.id].append(permission)
def add_many(self, assets_or_nodes, system_users, actions):
if any([assets_or_nodes, system_users, actions]):
return
iterable = itertools.product(assets_or_nodes, system_users, actions)
for source, sysuser, action in iterable:
permission = FlatPermission(source, sysuser, action)
self.add(permission)
def clean(self):
pass
class FlatPermission:
def __init__(self, asset_or_node, system_user, action):
self.id = asset_or_node.id
self.source = asset_or_node
self.system_user = system_user
self.action = action
def __eq__(self, other):
pass
class AssetPermissionUtil(AssetPermissionCacheMixin):
get_permissions_map = {
"User": get_user_permissions,
......@@ -344,19 +372,15 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
def get_nodes_direct(self):
"""
返回用户/组授权规则直接关联的节点
:return: {asset1: {system_user1: {'actions': set()},}}
:return: {node1: {system_user1: {'actions': set()},}}
"""
nodes = defaultdict(dict)
permissions = self.permissions.prefetch_related('nodes', 'system_users', 'actions')
nodes = FlatPermissionQueryset()
permissions = self.permissions
for perm in permissions:
actions = perm.actions.all()
for node in perm.nodes.all():
system_users = perm.system_users.all()
system_users = self._structured_system_user(system_users, actions)
nodes[node].update(system_users)
self.tree.add_nodes(nodes.keys())
# 替换成优化过的node
nodes = {self.tree.node_util.get_node_by_key(k.key): v for k, v in nodes.items()}
system_users = perm.system_users.all()
_nodes = perm.nodes.all()
nodes.add_many(_nodes, system_users, actions)
return nodes
@timeit
......@@ -385,24 +409,18 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
assets = self.get_assets_direct()
nodes = self.get_nodes_direct()
# for node, system_users in nodes.items():
# print(9999, node)
# _assets = node.get_all_valid_assets()
# print(".......... end .......")
# print(">>>>> Node<<<<<<<<<<<<: ", node.value)
# _assets = list(node.get_all_valid_assets())
# for asset in _assets:
# print(">>asset")
# for system_user, attr_dict in system_users.items():
# print(">>>system user")
# if not asset.has_protocol(system_user.protocol):
# continue
# if system_user in assets[asset]:
# actions = assets[asset][system_user]['actions']
# attr_dict['actions'].update(actions)
# system_users.update({system_user: attr_dict})
# print("<<<system user")
# print("<<<asset")
# assets[asset].update(system_users)
# print(">>>>>>")
#
__assets = defaultdict(set)
for asset, system_users in assets.items():
for system_user, attr_dict in system_users.items():
......@@ -507,8 +525,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
'id': asset.id,
'hostname': asset.hostname,
'ip': asset.ip,
'protocols': [{"name": p.name, "port": p.port}
for p in asset.protocols.all()],
'protocols': [str(p) for p in asset.protocols.all()],
'platform': asset.platform,
'domain': None if not asset.domain else asset.domain.id,
'is_active': asset.is_active,
......
......@@ -58,8 +58,6 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
assets_id = assets_id.split(",")
assets = Asset.objects.filter(id__in=assets_id)
form['assets'].initial = assets
form['actions'].initial = Action.objects.get(name=PERMS_ACTION_NAME_ALL)
return form
def get_context_data(self, **kwargs):
......
......@@ -277,7 +277,7 @@ function APIUpdateAttr(props) {
}).done(function(data, textStatue, jqXHR) {
if (flash_message) {
var msg = "";
if (user_fail_message) {
if (user_success_message) {
msg = user_success_message;
} else {
msg = default_success_message;
......@@ -635,7 +635,7 @@ jumpserver.initServerSideDataTable = function (options) {
columns: options.columns || [],
select: options.select || select,
language: jumpserver.language,
lengthMenu: [[15, 25, 50, 9999], [15, 25, 50, 'All']]
lengthMenu: options.lengthMenu || [[15, 25, 50, 9999], [15, 25, 50, 'All']]
});
table.selected = [];
table.selected_rows = [];
......@@ -1072,3 +1072,27 @@ function htmlEscape ( d ) {
d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
d;
}
function objectAttrsIsList(obj, attrs) {
attrs.forEach(function (attr) {
if (obj[attr] && !(obj[attr] instanceof Array)){
obj[attr] = [obj[attr]]
}
})
}
function objectAttrsIsDatetime(obj, attrs) {
attrs.forEach(function (attr) {
obj[attr] = new Date(obj[attr]).toISOString();
})
}
function objectAttrsIsBool(obj, attrs) {
attrs.forEach(function (attr) {
if (!obj[attr]) {
obj[attr] = false
} else if (['on', '1'].includes(obj[attr])) {
obj[attr] = true
}
})
}
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