Commit 83f220d7 authored by BaiJiangJie's avatar BaiJiangJie Committed by 老广

[Feature] 添加命令记录下载功能 (#1559)

* [Feature] 添加命令记录下载功能

* [Update] 文案修改,导出记录、提交,取消全部命令导出

* [Update] 命令导出,修复时间问题
parent 8e42a657
......@@ -93,7 +93,7 @@ class DatetimeSearchMixin:
date_format = '%Y-%m-%d'
date_from = date_to = None
def get(self, request, *args, **kwargs):
def get_date_range(self):
date_from_s = self.request.GET.get('date_from')
date_to_s = self.request.GET.get('date_to')
......@@ -113,6 +113,9 @@ class DatetimeSearchMixin:
)
else:
self.date_to = timezone.now()
def get(self, request, *args, **kwargs):
self.get_date_range()
return super().get(request, *args, **kwargs)
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-07-13 19:20+0800\n"
"POT-Creation-Date: 2018-07-19 18:29+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"
......@@ -445,7 +445,7 @@ msgstr "默认资产组"
#: terminal/templates/terminal/session_list.html:71 users/forms.py:282
#: users/models/user.py:31 users/models/user.py:333
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:361
#: users/templates/users/user_group_list.html:13 users/views/user.py:367
msgid "User"
msgstr "用户"
......@@ -685,6 +685,7 @@ msgstr "重置"
#: common/templates/common/security_setting.html:71
#: common/templates/common/terminal_setting.html:108
#: perms/templates/perms/asset_permission_create_update.html:70
#: terminal/templates/terminal/command_list.html:103
#: terminal/templates/terminal/session_list.html:126
#: terminal/templates/terminal/terminal_update.html:48
#: users/templates/users/_user.html:47
......@@ -814,7 +815,7 @@ msgstr "选择节点"
#: users/templates/users/user_detail.html:374
#: users/templates/users/user_detail.html:399
#: users/templates/users/user_detail.html:422
#: users/templates/users/user_detail.html:458
#: users/templates/users/user_detail.html:466
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_list.html:200
......@@ -1005,7 +1006,7 @@ msgstr "存在资产,不能删除"
#: assets/templates/assets/system_user_list.html:134
#: users/templates/users/user_detail.html:369
#: users/templates/users/user_detail.html:394
#: users/templates/users/user_detail.html:453
#: users/templates/users/user_detail.html:461
#: users/templates/users/user_group_list.html:81
#: users/templates/users/user_list.html:195
msgid "Are you sure?"
......@@ -2002,7 +2003,7 @@ msgstr "文档"
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:343
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:349
msgid "Profile"
msgstr "个人信息"
......@@ -2059,13 +2060,13 @@ msgstr "关闭"
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/login.py:330 users/views/login.py:388 users/views/user.py:65
#: users/views/user.py:80 users/views/user.py:102 users/views/user.py:175
#: users/views/user.py:330 users/views/user.py:380 users/views/user.py:415
#: users/views/login.py:332 users/views/login.py:390 users/views/user.py:67
#: users/views/user.py:82 users/views/user.py:104 users/views/user.py:180
#: users/views/user.py:336 users/views/user.py:386 users/views/user.py:421
msgid "Users"
msgstr "用户管理"
#: templates/_nav.html:13 users/views/user.py:66
#: templates/_nav.html:13 users/views/user.py:68
msgid "User list"
msgstr "用户列表"
......@@ -2093,7 +2094,7 @@ msgstr "命令记录"
msgid "Web terminal"
msgstr "Web终端"
#: templates/_nav.html:51 terminal/views/command.py:47
#: templates/_nav.html:51 terminal/views/command.py:49
#: terminal/views/session.py:75 terminal/views/session.py:93
#: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58
......@@ -2202,13 +2203,17 @@ msgstr "参数"
msgid "Goto"
msgstr "转到"
#: terminal/templates/terminal/command_list.html:99
msgid "Export command"
msgstr "导出命令"
#: terminal/templates/terminal/session_detail.html:17
#: terminal/views/session.py:116
msgid "Session detail"
msgstr "会话详情"
#: terminal/templates/terminal/session_detail.html:28
#: terminal/views/command.py:48
#: terminal/views/command.py:50
msgid "Command list"
msgstr "命令记录列表"
......@@ -2324,7 +2329,7 @@ msgid ""
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
msgstr "你可以使用ssh客户端工具连接终端"
#: users/api.py:221 users/templates/users/login.html:50
#: users/api.py:226 users/templates/users/login.html:50
msgid "Log in frequently and try again later"
msgstr "登录频繁, 稍后重试"
......@@ -2725,7 +2730,7 @@ msgid "Setting"
msgstr "设置"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:80
#: users/templates/users/user_list.html:16 users/views/user.py:82
msgid "Create user"
msgstr "创建用户"
......@@ -2734,7 +2739,7 @@ msgid "Reset link will be generated and sent to the user. "
msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:176
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:181
msgid "User detail"
msgstr "用户详情"
......@@ -2772,7 +2777,7 @@ msgid "Send reset ssh key mail"
msgstr "发送重置密钥邮件"
#: users/templates/users/user_detail.html:186
#: users/templates/users/user_detail.html:444
#: users/templates/users/user_detail.html:446
msgid "Unblock user"
msgstr "解除登录限制"
......@@ -2818,7 +2823,7 @@ msgstr "更新ssh密钥成功"
msgid "User SSH public key update"
msgstr "ssh密钥"
#: users/templates/users/user_detail.html:454
#: users/templates/users/user_detail.html:462
msgid "After unlocking the user, the user can log in normally."
msgstr "解除用户登录限制后,此用户即可正常登录"
......@@ -2878,8 +2883,8 @@ msgstr "用户删除失败"
msgid "Administrator Settings force MFA login"
msgstr "管理员设置强制使用MFA登录"
#: users/templates/users/user_profile.html:116 users/views/user.py:205
#: users/views/user.py:259
#: users/templates/users/user_profile.html:116 users/views/user.py:211
#: users/views/user.py:265
msgid "User groups"
msgstr "用户组"
......@@ -2925,7 +2930,7 @@ msgid ""
"corresponding private key."
msgstr "新的公钥已设置成功,请下载对应的私钥"
#: users/templates/users/user_update.html:4 users/views/user.py:103
#: users/templates/users/user_update.html:4 users/views/user.py:105
msgid "Update user"
msgstr "更新用户"
......@@ -3079,104 +3084,104 @@ msgstr "更新用户组"
msgid "User group granted asset"
msgstr "用户组授权资产"
#: users/views/login.py:75
#: users/views/login.py:76
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:178 users/views/user.py:500 users/views/user.py:525
#: users/views/login.py:180 users/views/user.py:506 users/views/user.py:531
msgid "MFA code invalid"
msgstr "MFA码认证失败"
#: users/views/login.py:207
#: users/views/login.py:209
msgid "Logout success"
msgstr "退出登录成功"
#: users/views/login.py:208
#: users/views/login.py:210
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:224
#: users/views/login.py:226
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:237
#: users/views/login.py:239
msgid "Send reset password message"
msgstr "发送重置密码邮件"
#: users/views/login.py:238
#: users/views/login.py:240
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:251
#: users/views/login.py:253
msgid "Reset password success"
msgstr "重置密码成功"
#: users/views/login.py:252
#: users/views/login.py:254
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:273 users/views/login.py:286
#: users/views/login.py:275 users/views/login.py:288
msgid "Token invalid or expired"
msgstr "Token错误或失效"
#: users/views/login.py:282
#: users/views/login.py:284
msgid "Password not same"
msgstr "密码不一致"
#: users/views/login.py:292 users/views/user.py:118 users/views/user.py:398
#: users/views/login.py:294 users/views/user.py:120 users/views/user.py:404
msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求"
#: users/views/login.py:330
#: users/views/login.py:332
msgid "First login"
msgstr "首次登陆"
#: users/views/login.py:389
#: users/views/login.py:391
msgid "Login log list"
msgstr "登录日志"
#: users/views/user.py:129
#: users/views/user.py:131
msgid "Bulk update user success"
msgstr "批量更新用户成功"
#: users/views/user.py:234
#: users/views/user.py:240
msgid "Invalid file."
msgstr "文件不合法"
#: users/views/user.py:331
#: users/views/user.py:337
msgid "User granted assets"
msgstr "用户授权资产"
#: users/views/user.py:362
#: users/views/user.py:368
msgid "Profile setting"
msgstr "个人信息设置"
#: users/views/user.py:381
#: users/views/user.py:387
msgid "Password update"
msgstr "密码更新"
#: users/views/user.py:416
#: users/views/user.py:422
msgid "Public key update"
msgstr "密钥更新"
#: users/views/user.py:457
#: users/views/user.py:463
msgid "Password invalid"
msgstr "用户名或密码无效"
#: users/views/user.py:551
#: users/views/user.py:557
msgid "MFA enable success"
msgstr "MFA 绑定成功"
#: users/views/user.py:552
#: users/views/user.py:558
msgid "MFA enable success, return login page"
msgstr "MFA 绑定成功,返回到登录页面"
#: users/views/user.py:554
#: users/views/user.py:560
msgid "MFA disable success"
msgstr "MFA 解绑成功"
#: users/views/user.py:555
#: users/views/user.py:561
msgid "MFA disable success, return login page"
msgstr "MFA 解绑成功,返回登录页面"
......
......@@ -92,27 +92,52 @@
{% endfor %}
</tbody>
</table>
<div id="actions" class="">
<div class="input-group">
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
<option value="export">{% trans 'Export command' %}</option>
</select>
<div class="input-group-btn pull-left" style="padding-left: 5px;">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Submit' %}
</button>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script>
$(document).ready(function () {
$('.footable').footable();
$('.select2').select2({
dropdownAutoWidth : true,
width: 'auto'
});
$('#date .input-daterange').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
});
$(document).ready(function () {
$('.footable').footable();
$('.select2').select2({
dropdownAutoWidth : true,
width: 'auto'
});
$('#date .input-daterange').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
});
})
.on('click', '#btn_bulk_update', function(){
var action = $('#slct_bulk_update').val();
var param_action = '&action=' + action;
var local_params = window.location.search;
if(!local_params){
param_action = '?action=' + action;
}
var params = local_params + param_action;
var pathname = window.location.pathname + 'export/';
var url = pathname + params;
window.open(url);
});
</script>
{% endblock %}
......
{% load common_tags %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Command Report</title>
<style>
*{
margin: 0;
padding: 0;
}
.background {
background-color: #535659;
padding-top: 50px;
padding-bottom: 50px;
}
.paper {
margin-left: 23%;
margin-right: 24%;
border: solid;
padding: 50px;
background-color: #fff;
}
h2 {
font-style: italic;
text-align: center;
}
.info {
width: 200px;
margin-left: 450px;
font-style: italic;
text-align: left;
padding-top: 20px;
padding-bottom: 20px;
}
.command {
margin-left: 10px;
}
.command-desc {
font-size: 12px;
}
.command-desc span {
float: right;
}
.command-input {
{#font-style: italic;#}
font-size: 15px;
margin-top: 10px;
margin-bottom: 10px;
}
.command-input span {
font-size: 13px;
}
.hr-line-dashed {
border-top: 1px dashed #000;
color: #000;
background-color: #fff;
height: 1px;
margin: 20px 0;
}
pre {
font-size: 12px;
}
</style>
</head>
<body>
<div class="background">
<div class="paper">
<h2>Command Report</h2>
<div class="info">
<p>total: {{ total_count }}</p>
<p>date: {{ now | ts_to_date }}</p>
</div>
<div class="hr-line-dashed"></div>
<div>
{% for command in queryset %}
<div class="command">
<p class="command-desc">
[{{ command.user}} {{ command.system_user }}@{{ command.asset }} {{ command.timestamp | ts_to_date }}]
<span>{{ forloop.counter }}</span>
</p>
<p class="command-input"><span>$ </span>{{ command.input }}</p>
<pre>{{ command.output }}</pre>
</div>
<div class="hr-line-dashed"></div>
{% endfor %}
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
......@@ -24,5 +24,6 @@ urlpatterns = [
# Command view
url(r'^command/$', views.CommandListView.as_view(), name='command-list'),
url(r'^command/export/$', views.CommandExportView.as_view(), name='command-export')
]
# -*- coding: utf-8 -*-
#
from django.views.generic import ListView
from django.views.generic import ListView, View
from django.conf import settings
from django.utils import timezone
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.template import loader
import time
from common.mixins import DatetimeSearchMixin, AdminUserRequiredMixin
from ..models import Command
from .. import utils
from ..backends import get_multi_command_storage
__all__ = ['CommandListView']
__all__ = ['CommandListView', 'CommandExportView']
common_storage = get_multi_command_storage()
......@@ -60,7 +62,43 @@ class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
return super().get_context_data(**kwargs)
class CommandExportView(DatetimeSearchMixin, AdminUserRequiredMixin, View):
model = Command
command = user = asset = system_user = action = ''
date_from = date_to = None
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
template = 'terminal/command_report.html'
context = {
'queryset': queryset,
'total_count': len(queryset),
'now': time.time(),
}
content = loader.render_to_string(template, context, request)
content_type = 'application/octet-stream'
response = HttpResponse(content, content_type)
filename = 'command-report-{}.html'.format(int(time.time()))
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
return response
def get_queryset(self):
self.get_date_range()
self.action = self.request.GET.get('action', '')
self.command = self.request.GET.get('command', '')
self.user = self.request.GET.get("user", '')
self.asset = self.request.GET.get('asset', '')
self.system_user = self.request.GET.get('system_user', '')
filter_kwargs = dict()
filter_kwargs['date_from'] = self.date_from
filter_kwargs['date_to'] = self.date_to
if self.user:
filter_kwargs['user'] = self.user
if self.asset:
filter_kwargs['asset'] = self.asset
if self.system_user:
filter_kwargs['system_user'] = self.system_user
if self.command:
filter_kwargs['input'] = self.command
queryset = common_storage.filter(**filter_kwargs)
return queryset
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