mirror of https://github.com/jumpserver/jumpserver
Merge branch 'dev' of github.com:jumpserver/jumpserver into github_dev
commit
de2416b173
|
@ -40,7 +40,7 @@ class SystemUserViewSet(BulkModelViewSet):
|
|||
permission_classes = (IsSuperUserOrAppUser,)
|
||||
|
||||
|
||||
class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView):
|
||||
class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
Get system user auth info
|
||||
"""
|
||||
|
@ -48,6 +48,11 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView):
|
|||
permission_classes = (IsSuperUserOrAppUser,)
|
||||
serializer_class = serializers.SystemUserAuthSerializer
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
instance.clear_auth()
|
||||
return Response(status=204)
|
||||
|
||||
|
||||
class SystemUserPushApi(generics.RetrieveAPIView):
|
||||
"""
|
||||
|
|
|
@ -107,6 +107,7 @@ class AssetUser(models.Model):
|
|||
def clear_auth(self):
|
||||
self._password = ''
|
||||
self._private_key = ''
|
||||
self._public_key = ''
|
||||
self.save()
|
||||
|
||||
def auto_gen_auth(self):
|
||||
|
|
|
@ -61,10 +61,14 @@ class Node(models.Model):
|
|||
return child
|
||||
|
||||
def get_children(self):
|
||||
return self.__class__.objects.filter(key__regex=r'^{}:[0-9]+$'.format(self.key))
|
||||
return self.__class__.objects.filter(
|
||||
key__regex=r'^{}:[0-9]+$'.format(self.key)
|
||||
)
|
||||
|
||||
def get_all_children(self):
|
||||
return self.__class__.objects.filter(key__startswith='{}:'.format(self.key))
|
||||
return self.__class__.objects.filter(
|
||||
key__startswith='{}:'.format(self.key)
|
||||
)
|
||||
|
||||
def get_family(self):
|
||||
children = list(self.get_all_children())
|
||||
|
|
|
@ -107,14 +107,14 @@
|
|||
</div>
|
||||
|
||||
<div class="col-sm-4" style="padding-left: 0;padding-right: 0">
|
||||
<div class="panel panel-primary only-ssh">
|
||||
<div class="panel panel-primary ">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Quick update' %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr class="no-borders-tr">
|
||||
<tr class="only-ssh">
|
||||
<td width="50%">{% trans 'Auto push' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
|
@ -130,8 +130,8 @@
|
|||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="no-borders-tr">
|
||||
{% if system_user.auto_push %}
|
||||
<tr class="only-ssh">
|
||||
<td width="50%">{% trans 'Push system user now' %}:</td>
|
||||
<td>
|
||||
<span style="float: right">
|
||||
|
@ -139,8 +139,8 @@
|
|||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% endif %}
|
||||
<tr class="only-ssh">
|
||||
<td width="50%">{% trans 'Test assets connective' %}:</td>
|
||||
<td>
|
||||
<span style="float: right">
|
||||
|
@ -149,6 +149,15 @@
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="50%">{% trans 'Clear auth' %}:</td>
|
||||
<td>
|
||||
<span style="float: right">
|
||||
<button type="button" class="btn btn-primary btn-xs btn-clear-auth" style="width: 54px">{% trans 'Clear' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{# <tr>#}
|
||||
{# <td width="50%">{% trans 'Change auth period' %}:</td>#}
|
||||
{# <td>#}
|
||||
|
@ -239,6 +248,7 @@ $(document).ready(function () {
|
|||
if($('#id_protocol_type').text() === 'rdp'){
|
||||
$('.only-ssh').addClass('hidden')
|
||||
}
|
||||
$(".panel-body .table tr:visible:first").addClass('no-borders-tr');
|
||||
$('.select2').select2()
|
||||
.on('select2:select', function(evt) {
|
||||
var data = evt.params.data;
|
||||
|
@ -321,6 +331,13 @@ $(document).ready(function () {
|
|||
success: success,
|
||||
flash_message: false
|
||||
});
|
||||
}).on('click', '.btn-clear-auth', function () {
|
||||
var the_url = '{% url "api-assets:system-user-auth-info" pk=system_user.id %}';
|
||||
APIUpdateAttr({
|
||||
url: the_url,
|
||||
method: 'DELETE',
|
||||
success_message: "{% trans 'Clear auth' %}" + " {% trans 'success' %}"
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: Jumpserver 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-08 17:24+0800\n"
|
||||
"POT-Creation-Date: 2018-05-17 11:32+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
||||
|
@ -17,22 +17,22 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: assets/api/node.py:96
|
||||
#: assets/api/node.py:106
|
||||
msgid "New node {}"
|
||||
msgstr "新节点 {}"
|
||||
|
||||
#: assets/api/node.py:225
|
||||
#: assets/api/node.py:242
|
||||
msgid "更新节点资产硬件信息: {}"
|
||||
msgstr ""
|
||||
|
||||
#: assets/api/node.py:238
|
||||
#: assets/api/node.py:255
|
||||
msgid "测试节点下资产是否可连接: {}"
|
||||
msgstr ""
|
||||
|
||||
#: assets/forms/asset.py:24 assets/models/asset.py:66 assets/models/user.py:103
|
||||
#: assets/templates/assets/asset_detail.html:183
|
||||
#: assets/templates/assets/asset_detail.html:191
|
||||
#: assets/templates/assets/system_user_detail.html:166 perms/models.py:33
|
||||
#: assets/templates/assets/system_user_detail.html:175 perms/models.py:33
|
||||
msgid "Nodes"
|
||||
msgstr "节点管理"
|
||||
|
||||
|
@ -438,7 +438,7 @@ msgstr "默认资产组"
|
|||
msgid "User"
|
||||
msgstr "用户"
|
||||
|
||||
#: assets/models/label.py:18 assets/models/node.py:15
|
||||
#: assets/models/label.py:18 assets/models/node.py:18
|
||||
#: assets/templates/assets/label_list.html:15 common/models.py:27
|
||||
msgid "Value"
|
||||
msgstr "值"
|
||||
|
@ -535,7 +535,7 @@ msgstr "测试系统用户可连接性: {}"
|
|||
msgid "定期测试系统用户可连接性: {}"
|
||||
msgstr ""
|
||||
|
||||
#: assets/tasks.py:401
|
||||
#: assets/tasks.py:402
|
||||
msgid "推送系统用户到入资产: {}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -660,7 +660,7 @@ msgstr "重置"
|
|||
#: common/templates/common/ldap_setting.html:60
|
||||
#: common/templates/common/terminal_setting.html:103
|
||||
#: perms/templates/perms/asset_permission_create_update.html:70
|
||||
#: terminal/templates/terminal/session_list.html:120
|
||||
#: terminal/templates/terminal/session_list.html:124
|
||||
#: terminal/templates/terminal/terminal_update.html:48
|
||||
#: users/templates/users/_user.html:47
|
||||
#: users/templates/users/forgot_password.html:44
|
||||
|
@ -782,8 +782,8 @@ msgstr "选择节点"
|
|||
|
||||
#: assets/templates/assets/admin_user_detail.html:100
|
||||
#: assets/templates/assets/asset_detail.html:200
|
||||
#: assets/templates/assets/asset_list.html:634
|
||||
#: assets/templates/assets/system_user_detail.html:183
|
||||
#: assets/templates/assets/asset_list.html:636
|
||||
#: assets/templates/assets/system_user_detail.html:192
|
||||
#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:22
|
||||
#: terminal/templates/terminal/session_detail.html:108
|
||||
#: users/templates/users/user_detail.html:362
|
||||
|
@ -963,19 +963,19 @@ msgstr "仅显示当前节点资产"
|
|||
msgid "Displays all child node assets"
|
||||
msgstr "显示所有子节点资产"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:215
|
||||
#: assets/templates/assets/asset_list.html:217
|
||||
msgid "Create node failed"
|
||||
msgstr "创建节点失败"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:227
|
||||
#: assets/templates/assets/asset_list.html:229
|
||||
msgid "Have child node, cancel"
|
||||
msgstr "存在子节点,不能删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:229
|
||||
#: assets/templates/assets/asset_list.html:231
|
||||
msgid "Have assets, cancel"
|
||||
msgstr "存在资产,不能删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:629
|
||||
#: assets/templates/assets/asset_list.html:631
|
||||
#: assets/templates/assets/system_user_list.html:133
|
||||
#: users/templates/users/user_detail.html:357
|
||||
#: users/templates/users/user_detail.html:382
|
||||
|
@ -984,20 +984,20 @@ msgstr "存在资产,不能删除"
|
|||
msgid "Are you sure?"
|
||||
msgstr "你确认吗?"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:630
|
||||
#: assets/templates/assets/asset_list.html:632
|
||||
msgid "This will delete the selected assets !!!"
|
||||
msgstr "删除选择资产"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:638
|
||||
#: assets/templates/assets/asset_list.html:640
|
||||
msgid "Asset Deleted."
|
||||
msgstr "已被删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:639
|
||||
#: assets/templates/assets/asset_list.html:644
|
||||
#: assets/templates/assets/asset_list.html:641
|
||||
#: assets/templates/assets/asset_list.html:646
|
||||
msgid "Asset Delete"
|
||||
msgstr "删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:643
|
||||
#: assets/templates/assets/asset_list.html:645
|
||||
msgid "Asset Deleting failed."
|
||||
msgstr "删除失败"
|
||||
|
||||
|
@ -1032,6 +1032,7 @@ msgid "Create gateway"
|
|||
msgstr "创建网关"
|
||||
|
||||
#: assets/templates/assets/domain_gateway_list.html:87
|
||||
#: assets/templates/assets/domain_gateway_list.html:89
|
||||
#: common/templates/common/email_setting.html:58
|
||||
#: common/templates/common/ldap_setting.html:58
|
||||
msgid "Test connection"
|
||||
|
@ -1080,10 +1081,23 @@ msgstr "家目录"
|
|||
msgid "Uid"
|
||||
msgstr "Uid"
|
||||
|
||||
#: assets/templates/assets/system_user_detail.html:174
|
||||
#: assets/templates/assets/system_user_detail.html:153
|
||||
#: assets/templates/assets/system_user_detail.html:339
|
||||
msgid "Clear auth"
|
||||
msgstr "清除认证信息"
|
||||
|
||||
#: assets/templates/assets/system_user_detail.html:156
|
||||
msgid "Clear"
|
||||
msgstr "清除"
|
||||
|
||||
#: assets/templates/assets/system_user_detail.html:183
|
||||
msgid "Add to node"
|
||||
msgstr "添加到节点"
|
||||
|
||||
#: assets/templates/assets/system_user_detail.html:339
|
||||
msgid "success"
|
||||
msgstr "成功"
|
||||
|
||||
#: assets/templates/assets/system_user_list.html:18
|
||||
#: assets/views/system_user.py:45
|
||||
msgid "Create system user"
|
||||
|
@ -2113,15 +2127,16 @@ msgstr "时长"
|
|||
msgid "Monitor"
|
||||
msgstr "监控"
|
||||
|
||||
#: terminal/templates/terminal/session_list.html:105
|
||||
#: terminal/templates/terminal/session_list.html:106
|
||||
#: terminal/templates/terminal/session_list.html:108
|
||||
msgid "Terminate"
|
||||
msgstr "终断"
|
||||
|
||||
#: terminal/templates/terminal/session_list.html:116
|
||||
#: terminal/templates/terminal/session_list.html:120
|
||||
msgid "Terminate selected"
|
||||
msgstr "终断所选"
|
||||
|
||||
#: terminal/templates/terminal/session_list.html:136
|
||||
#: terminal/templates/terminal/session_list.html:140
|
||||
msgid "Terminate task send, waiting ..."
|
||||
msgstr "终断任务已发送,请等待"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from rest_framework.views import APIView, Response
|
|||
from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView
|
||||
from rest_framework import viewsets
|
||||
|
||||
from common.utils import set_or_append_attr_bulk
|
||||
from common.utils import set_or_append_attr_bulk, get_object_or_none
|
||||
from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser
|
||||
from .utils import AssetPermissionUtil
|
||||
from .models import AssetPermission
|
||||
|
@ -147,8 +147,13 @@ class UserGrantedNodeAssetsApi(ListAPIView):
|
|||
user = get_object_or_404(User, id=user_id)
|
||||
else:
|
||||
user = self.request.user
|
||||
node = get_object_or_404(Node, id=node_id)
|
||||
nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
|
||||
node = get_object_or_none(Node, id=node_id)
|
||||
|
||||
if not node:
|
||||
unnode = [node for node in nodes if node.name == 'Unnode']
|
||||
node = unnode[0] if unnode else None
|
||||
|
||||
assets = nodes.get(node, [])
|
||||
for asset, system_users in assets.items():
|
||||
asset.system_users_granted = system_users
|
||||
|
|
|
@ -13,7 +13,6 @@ logger = get_logger(__file__)
|
|||
|
||||
|
||||
class AssetPermissionUtil:
|
||||
|
||||
@staticmethod
|
||||
def get_user_permissions(user):
|
||||
return AssetPermission.objects.all().valid().filter(users=user)
|
||||
|
@ -122,6 +121,24 @@ class AssetPermissionUtil:
|
|||
nodes[node].update(set(_system_users))
|
||||
return nodes
|
||||
|
||||
@classmethod
|
||||
def get_user_nodes_inherit_group(cls, user):
|
||||
nodes = defaultdict(set)
|
||||
groups = user.groups.all()
|
||||
for group in groups:
|
||||
_nodes = cls.get_user_group_nodes(group)
|
||||
for node, system_users in _nodes.items():
|
||||
nodes[node].update(set(system_users))
|
||||
return nodes
|
||||
|
||||
@classmethod
|
||||
def get_user_nodes(cls, user):
|
||||
nodes = cls.get_user_nodes_direct(user)
|
||||
nodes_inherit = cls.get_user_nodes_inherit_group(user)
|
||||
for node, system_users in nodes_inherit.items():
|
||||
nodes[node].update(set(system_users))
|
||||
return nodes
|
||||
|
||||
@classmethod
|
||||
def get_user_nodes_assets_direct(cls, user):
|
||||
assets = defaultdict(set)
|
||||
|
@ -164,15 +181,24 @@ class AssetPermissionUtil:
|
|||
:param user:
|
||||
:return: {node: {asset: set(su1, su2)}}
|
||||
"""
|
||||
from assets.models import Node
|
||||
unnode = Node(value='Unnode')
|
||||
nodes = defaultdict(dict)
|
||||
for _node in cls.get_user_nodes(user):
|
||||
children = _node.get_family()
|
||||
for node in children:
|
||||
nodes[node] = defaultdict(set)
|
||||
nodes[unnode] = defaultdict(set)
|
||||
_assets = cls.get_user_assets(user)
|
||||
for asset, _system_users in _assets.items():
|
||||
_nodes = asset.get_nodes()
|
||||
in_node = False
|
||||
for node in _nodes:
|
||||
if asset in nodes[node]:
|
||||
if node in nodes:
|
||||
in_node = True
|
||||
nodes[node][asset].update(_system_users)
|
||||
else:
|
||||
nodes[node][asset] = _system_users
|
||||
if not in_node:
|
||||
nodes[unnode][asset].update(_system_users)
|
||||
return nodes
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.core.cache import cache
|
|||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils import timezone
|
||||
from django.core.files.storage import default_storage
|
||||
from django.http.response import HttpResponseRedirectBase
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -25,7 +26,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \
|
|||
SessionSerializer, TaskSerializer, ReplaySerializer
|
||||
from .hands import IsSuperUserOrAppUser, IsAppUser, \
|
||||
IsSuperUserOrAppUserOrUserReadonly
|
||||
from .backends import get_command_store, get_multi_command_store, \
|
||||
from .backends import get_command_storage, get_multi_command_storage, \
|
||||
SessionCommandSerializer
|
||||
|
||||
logger = logging.getLogger(__file__)
|
||||
|
@ -227,8 +228,8 @@ class CommandViewSet(viewsets.ViewSet):
|
|||
}
|
||||
|
||||
"""
|
||||
command_store = get_command_store()
|
||||
multi_command_storage = get_multi_command_store()
|
||||
command_store = get_command_storage()
|
||||
multi_command_storage = get_multi_command_storage()
|
||||
serializer_class = SessionCommandSerializer
|
||||
permission_classes = (IsSuperUserOrAppUser,)
|
||||
|
||||
|
@ -291,19 +292,20 @@ class SessionReplayViewSet(viewsets.ViewSet):
|
|||
url = default_storage.url(path)
|
||||
return redirect(url)
|
||||
else:
|
||||
configs = settings.TERMINAL_REPLAY_STORAGE.items()
|
||||
configs = settings.TERMINAL_REPLAY_STORAGE
|
||||
configs = [cfg for cfg in configs if cfg['TYPE'] != 'server']
|
||||
if not configs:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
for name, config in configs:
|
||||
client = jms_storage.init(config)
|
||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||
file_path = os.path.join(date, str(self.session.id) + '.replay.gz')
|
||||
target_path = default_storage.base_location + '/' + path
|
||||
|
||||
if client and client.has_file(file_path) and \
|
||||
client.download_file(file_path, target_path):
|
||||
return redirect(default_storage.url(path))
|
||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||
file_path = os.path.join(date, str(self.session.id) + '.replay.gz')
|
||||
target_path = default_storage.base_location + '/' + path
|
||||
storage = jms_storage.get_multi_object_storage(configs)
|
||||
ok, err = storage.download(file_path, target_path)
|
||||
if ok:
|
||||
return redirect(default_storage.url(path))
|
||||
else:
|
||||
logger.error("Failed download replay file: {}".format(err))
|
||||
return HttpResponseNotFound()
|
||||
|
||||
|
||||
|
@ -313,34 +315,14 @@ class SessionReplayV2ViewSet(SessionReplayViewSet):
|
|||
session = None
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
session_id = kwargs.get('pk')
|
||||
self.session = get_object_or_404(Session, id=session_id)
|
||||
path = self.gen_session_path()
|
||||
response = super().retrieve(request, *args, **kwargs)
|
||||
data = {
|
||||
'type': 'guacamole' if self.session.protocol == 'rdp' else 'json',
|
||||
'src': '',
|
||||
}
|
||||
|
||||
if default_storage.exists(path):
|
||||
url = default_storage.url(path)
|
||||
data['src'] = url
|
||||
if isinstance(response, HttpResponseRedirectBase):
|
||||
data['src'] = response.url
|
||||
return Response(data)
|
||||
else:
|
||||
configs = settings.TERMINAL_REPLAY_STORAGE.items()
|
||||
if not configs:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
for name, config in configs:
|
||||
client = jms_storage.init(config)
|
||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||
file_path = os.path.join(date, str(self.session.id) + '.replay.gz')
|
||||
target_path = default_storage.base_location + '/' + path
|
||||
|
||||
if client and client.has_file(file_path) and \
|
||||
client.download_file(file_path, target_path):
|
||||
url = default_storage.url(path)
|
||||
data['src'] = url
|
||||
return Response(data)
|
||||
return HttpResponseNotFound()
|
||||
|
||||
|
||||
|
|
|
@ -7,19 +7,19 @@ TYPE_ENGINE_MAPPING = {
|
|||
}
|
||||
|
||||
|
||||
def get_command_store():
|
||||
params = settings.COMMAND_STORAGE
|
||||
engine_class = import_module(params['ENGINE'])
|
||||
storage = engine_class.CommandStore(params)
|
||||
def get_command_storage():
|
||||
config = settings.COMMAND_STORAGE
|
||||
engine_class = import_module(config['ENGINE'])
|
||||
storage = engine_class.CommandStore(config)
|
||||
return storage
|
||||
|
||||
|
||||
def get_terminal_command_store():
|
||||
def get_terminal_command_storages():
|
||||
storage_list = {}
|
||||
for name, params in settings.TERMINAL_COMMAND_STORAGE.items():
|
||||
tp = params['TYPE']
|
||||
if tp == 'server':
|
||||
storage = get_command_store()
|
||||
storage = get_command_storage()
|
||||
else:
|
||||
if not TYPE_ENGINE_MAPPING.get(tp):
|
||||
continue
|
||||
|
@ -29,9 +29,9 @@ def get_terminal_command_store():
|
|||
return storage_list
|
||||
|
||||
|
||||
def get_multi_command_store():
|
||||
def get_multi_command_storage():
|
||||
from .command.multi import CommandStore
|
||||
storage_list = get_terminal_command_store().values()
|
||||
storage_list = get_terminal_command_storages().values()
|
||||
storage = CommandStore(storage_list)
|
||||
return storage
|
||||
|
||||
|
|
|
@ -1,41 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from jms_es_sdk import ESStore
|
||||
from jms_storage.es import ESStorage
|
||||
from .base import CommandBase
|
||||
from .models import AbstractSessionCommand
|
||||
|
||||
|
||||
class CommandStore(CommandBase, ESStore):
|
||||
class CommandStore(ESStorage, CommandBase):
|
||||
def __init__(self, params):
|
||||
hosts = params.get('HOSTS', ['http://localhost'])
|
||||
ESStore.__init__(self, hosts=hosts)
|
||||
|
||||
def save(self, command):
|
||||
return ESStore.save(self, command)
|
||||
|
||||
def bulk_save(self, commands):
|
||||
return ESStore.bulk_save(self, commands)
|
||||
super().__init__(params)
|
||||
|
||||
def filter(self, date_from=None, date_to=None,
|
||||
user=None, asset=None, system_user=None,
|
||||
input=None, session=None):
|
||||
|
||||
data = ESStore.filter(
|
||||
self, date_from=date_from, date_to=date_to,
|
||||
user=user, asset=asset, system_user=system_user,
|
||||
input=input, session=session
|
||||
)
|
||||
data = super().filter(date_from=date_from, date_to=date_to,
|
||||
user=user, asset=asset, system_user=system_user,
|
||||
input=input, session=session)
|
||||
return AbstractSessionCommand.from_multi_dict(
|
||||
[item["_source"] for item in data["hits"] if item]
|
||||
)
|
||||
|
||||
def count(self, date_from=None, date_to=None,
|
||||
user=None, asset=None, system_user=None,
|
||||
input=None, session=None):
|
||||
amount = ESStore.count(
|
||||
self, date_from=date_from, date_to=date_to,
|
||||
user=user, asset=asset, system_user=system_user,
|
||||
input=input, session=session
|
||||
)
|
||||
return amount
|
||||
|
|
|
@ -9,7 +9,7 @@ from rest_framework_bulk.serializers import BulkListSerializer
|
|||
from common.mixins import BulkSerializerMixin
|
||||
from common.utils import get_object_or_none
|
||||
from .models import Terminal, Status, Session, Task
|
||||
from .backends import get_multi_command_store
|
||||
from .backends import get_multi_command_storage
|
||||
|
||||
|
||||
class TerminalSerializer(serializers.ModelSerializer):
|
||||
|
@ -47,7 +47,7 @@ class TerminalSerializer(serializers.ModelSerializer):
|
|||
|
||||
class SessionSerializer(serializers.ModelSerializer):
|
||||
command_amount = serializers.SerializerMethodField()
|
||||
command_store = get_multi_command_store()
|
||||
command_store = get_multi_command_storage()
|
||||
|
||||
class Meta:
|
||||
model = Session
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from django import template
|
||||
from ..backends import get_multi_command_store
|
||||
from ..backends import get_multi_command_storage
|
||||
|
||||
register = template.Library()
|
||||
command_store = get_multi_command_store()
|
||||
command_store = get_multi_command_storage()
|
||||
|
||||
|
||||
@register.filter
|
||||
|
|
|
@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _
|
|||
from common.mixins import DatetimeSearchMixin, AdminUserRequiredMixin
|
||||
from ..models import Command
|
||||
from .. import utils
|
||||
from ..backends import get_multi_command_store
|
||||
from ..backends import get_multi_command_storage
|
||||
|
||||
__all__ = ['CommandListView']
|
||||
common_storage = get_multi_command_store()
|
||||
common_storage = get_multi_command_storage()
|
||||
|
||||
|
||||
class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.conf import settings
|
|||
from users.utils import AdminUserRequiredMixin
|
||||
from common.mixins import DatetimeSearchMixin
|
||||
from ..models import Session, Command, Terminal
|
||||
from ..backends import get_multi_command_store
|
||||
from ..backends import get_multi_command_storage
|
||||
from .. import utils
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ __all__ = [
|
|||
'SessionDetailView',
|
||||
]
|
||||
|
||||
command_store = get_multi_command_store()
|
||||
command_store = get_multi_command_storage()
|
||||
|
||||
|
||||
class SessionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
|
||||
|
|
|
@ -11,7 +11,7 @@ __all__ = ['UserGroup']
|
|||
|
||||
class UserGroup(NoDeleteModelMixin):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, null=True,
|
||||
verbose_name=_('Date created'))
|
||||
|
|
|
@ -40,7 +40,6 @@ itsdangerous==0.24
|
|||
itypes==1.1.0
|
||||
Jinja2==2.10
|
||||
jmespath==0.9.3
|
||||
jms-es-sdk
|
||||
kombu==4.0.2
|
||||
ldap3==2.4
|
||||
MarkupSafe==1.0
|
||||
|
@ -62,7 +61,7 @@ pytz==2017.3
|
|||
PyYAML==3.12
|
||||
redis==2.10.6
|
||||
requests==2.18.4
|
||||
jms-storage==0.0.13
|
||||
jms-storage==0.0.17
|
||||
s3transfer==0.1.13
|
||||
simplejson==3.13.2
|
||||
six==1.11.0
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
from collections import Counter
|
||||
import django
|
||||
from django.db.models import Count
|
||||
|
||||
|
||||
if os.path.exists('../apps'):
|
||||
sys.path.insert(0, '../apps')
|
||||
elif os.path.exists('./apps'):
|
||||
sys.path.insert(0, './apps')
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings")
|
||||
django.setup()
|
||||
|
||||
from users.models import UserGroup
|
||||
|
||||
|
||||
def clean_group(interactive=True):
|
||||
groups = UserGroup.objects.all()
|
||||
groups_name_list = groups.values_list('name', flat=True)
|
||||
groups_with_info = groups.annotate(Count('users'))\
|
||||
.annotate(Count('asset_permissions'))
|
||||
|
||||
counter = Counter(groups_name_list)
|
||||
for name, count in counter.items():
|
||||
if count == 0:
|
||||
continue
|
||||
groups_duplicate = groups_with_info.filter(name=name)
|
||||
need_clean_count = groups_duplicate.count()
|
||||
|
||||
for group in groups_duplicate:
|
||||
need_clean = True
|
||||
if group.users__count > 0:
|
||||
need_clean = False
|
||||
elif group.asset_permissions__count > 0:
|
||||
need_clean = False
|
||||
elif need_clean_count == 1:
|
||||
need_clean = False
|
||||
|
||||
if need_clean:
|
||||
confirm = True
|
||||
if interactive:
|
||||
confirm = False
|
||||
while True:
|
||||
confirm = input(
|
||||
"Delete user group <{}>, create at {}? ([y]/n)".format(
|
||||
name, group.date_created)
|
||||
)
|
||||
if confirm.lower() == "y":
|
||||
confirm = True
|
||||
break
|
||||
elif confirm.lower() == "n":
|
||||
confirm = False
|
||||
break
|
||||
else:
|
||||
print("No valid input")
|
||||
continue
|
||||
if confirm:
|
||||
group.delete()
|
||||
print("Delete success: {}".format(name))
|
||||
need_clean_count -= 1
|
||||
else:
|
||||
continue
|
||||
|
||||
if __name__ == '__main__':
|
||||
clean_group()
|
Loading…
Reference in New Issue