mirror of https://github.com/tp4a/teleport
rdp播放功能部分可用(支持播放FreeRDP的录像,但是不能播放MSCST的录像)。
parent
a3e0fea4d4
commit
d6bcdeb42d
|
@ -1174,92 +1174,124 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf)
|
|||
}
|
||||
|
||||
// 判断参数是否正确
|
||||
if (!jsRoot["host"].isString())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (!jsRoot["port"].isInt())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (!jsRoot["tail"].isString())
|
||||
// if (!jsRoot["host"].isString())
|
||||
// {
|
||||
// _create_json_ret(buf, TPE_PARAM);
|
||||
// return;
|
||||
// }
|
||||
// if (!jsRoot["port"].isInt())
|
||||
// {
|
||||
// _create_json_ret(buf, TPE_PARAM);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!jsRoot["rid"].isInt()
|
||||
|| !jsRoot["web"].isString()
|
||||
|| !jsRoot["sid"].isString()
|
||||
|| !jsRoot["user"].isString()
|
||||
|| !jsRoot["acc"].isString()
|
||||
|| !jsRoot["host"].isString()
|
||||
|| !jsRoot["start"].isString()
|
||||
)
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if (!jsRoot["tail"].isString())
|
||||
// {
|
||||
// _create_json_ret(buf, TPE_PARAM);
|
||||
// return;
|
||||
// }
|
||||
|
||||
int rid = jsRoot["rid"].asInt();
|
||||
ex_astr a_url_base = jsRoot["web"].asCString();
|
||||
ex_astr a_sid = jsRoot["sid"].asCString();
|
||||
ex_astr a_user = jsRoot["user"].asCString();
|
||||
ex_astr a_acc = jsRoot["acc"].asCString();
|
||||
ex_astr a_host = jsRoot["host"].asCString();
|
||||
int port = jsRoot["port"].asInt();
|
||||
ex_astr a_tail = jsRoot["tail"].asCString();
|
||||
ex_astr server_ip;
|
||||
if (isIPAddress(a_host.c_str()))
|
||||
{
|
||||
server_ip = a_host;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr, **pptr;
|
||||
struct hostent *hptr;
|
||||
char IP[128] = { 0 };
|
||||
/* 取得命令后第一个参数,即要解析的域名或主机名 */
|
||||
ptr = (char*)a_host.c_str();
|
||||
/* 调用gethostbyname()。调用结果都存在hptr中 */
|
||||
if ((hptr = gethostbyname(ptr)) == NULL)
|
||||
{
|
||||
//printf("gethostbyname error for host:%s/n", ptr);
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
/* 将主机的规范名打出来 */
|
||||
//printf("official hostname:%s/n", hptr->h_name);
|
||||
/* 主机可能有多个别名,将所有别名分别打出来 */
|
||||
//for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
|
||||
// printf(" alias:%s/n", *pptr);
|
||||
/* 根据地址类型,将地址打出来 */
|
||||
char szbuf[1204] = { 0 };
|
||||
switch (hptr->h_addrtype)
|
||||
{
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
pptr = hptr->h_addr_list;
|
||||
/* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */
|
||||
ex_astr a_start = jsRoot["start"].asCString();
|
||||
//ex_astr a_tail = jsRoot["tail"].asCString();
|
||||
|
||||
for (; *pptr != NULL; pptr++)
|
||||
inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP));
|
||||
server_ip = IP;
|
||||
break;
|
||||
default:
|
||||
printf("unknown address type/n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
char szURL[256] = { 0 };
|
||||
sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
|
||||
ex_astr a_url = szURL;
|
||||
ex_wstr w_url;
|
||||
ex_astr2wstr(a_url, w_url);
|
||||
char cmd_args[1024] = { 0 };
|
||||
ex_strformat(cmd_args, 1023, "%d \"%s\" \"%09d-%s-%s-%s-%s\"", rid, a_sid.c_str(), rid, a_user.c_str(), a_acc.c_str(), a_host.c_str(), a_start.c_str());
|
||||
|
||||
char szHost[256] = { 0 };
|
||||
sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
|
||||
|
||||
a_host = szHost;
|
||||
ex_wstr w_host;
|
||||
ex_astr2wstr(a_host, w_host);
|
||||
// ex_astr a_host = jsRoot["host"].asCString();
|
||||
// int port = jsRoot["port"].asInt();
|
||||
// ex_astr a_tail = jsRoot["tail"].asCString();
|
||||
// ex_astr server_ip;
|
||||
// if (isIPAddress(a_host.c_str()))
|
||||
// {
|
||||
// server_ip = a_host;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// char *ptr, **pptr;
|
||||
// struct hostent *hptr;
|
||||
// char IP[128] = { 0 };
|
||||
// // 取得命令后第一个参数,即要解析的域名或主机名
|
||||
// ptr = (char*)a_host.c_str();
|
||||
// // 调用gethostbyname()。调用结果都存在hptr中
|
||||
// if ((hptr = gethostbyname(ptr)) == NULL)
|
||||
// {
|
||||
// //printf("gethostbyname error for host:%s/n", ptr);
|
||||
// _create_json_ret(buf, TPE_PARAM);
|
||||
// return;
|
||||
// }
|
||||
// // 将主机的规范名打出来
|
||||
// //printf("official hostname:%s/n", hptr->h_name);
|
||||
// // 主机可能有多个别名,将所有别名分别打出来
|
||||
// //for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
|
||||
// // printf(" alias:%s/n", *pptr);
|
||||
// // 根据地址类型,将地址打出来
|
||||
// char szbuf[1204] = { 0 };
|
||||
// switch (hptr->h_addrtype)
|
||||
// {
|
||||
// case AF_INET:
|
||||
// case AF_INET6:
|
||||
// pptr = hptr->h_addr_list;
|
||||
// // 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数
|
||||
//
|
||||
// for (; *pptr != NULL; pptr++)
|
||||
// inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP));
|
||||
// server_ip = IP;
|
||||
// break;
|
||||
// default:
|
||||
// printf("unknown address type/n");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// char szURL[256] = { 0 };
|
||||
// sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
|
||||
// ex_astr a_url = szURL;
|
||||
ex_wstr w_url_base;
|
||||
ex_astr2wstr(a_url_base, w_url_base);
|
||||
ex_wstr w_cmd_args;
|
||||
ex_astr2wstr(cmd_args, w_cmd_args);
|
||||
|
||||
// char szHost[256] = { 0 };
|
||||
// sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
|
||||
//
|
||||
// a_host = szHost;
|
||||
// ex_wstr w_host;
|
||||
// ex_astr2wstr(a_host, w_host);
|
||||
|
||||
ex_wstr w_exe_path;
|
||||
w_exe_path = _T("\"");
|
||||
w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\"");
|
||||
w_exe_path += _T(" ");
|
||||
w_exe_path += w_url;
|
||||
|
||||
w_exe_path += _T(" ");
|
||||
w_exe_path += w_host;
|
||||
w_exe_path += _T(" \"");
|
||||
w_exe_path += w_url_base;
|
||||
w_exe_path += _T("\" ");
|
||||
w_exe_path += w_cmd_args;
|
||||
|
||||
Json::Value root_ret;
|
||||
ex_astr utf8_path;
|
||||
ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8);
|
||||
root_ret["path"] = utf8_path;
|
||||
root_ret["cmdline"] = utf8_path;
|
||||
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __TS_HTTP_RPC_H__
|
||||
#define __TS_HTTP_RPC_H__
|
||||
|
||||
#include "../../external/mongoose/mongoose.h"
|
||||
|
||||
#include "ts_const.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -10,7 +12,6 @@
|
|||
#include <ex.h>
|
||||
#include <json/json.h>
|
||||
|
||||
#include "../../external/mongoose/mongoose.h"
|
||||
|
||||
/*
|
||||
//=================================================================
|
||||
|
|
|
@ -54,6 +54,9 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
|
|||
// EXLOGV("\n");
|
||||
return TPE_NETWORK;
|
||||
}
|
||||
if (body.length() == 0) {
|
||||
return TPE_NETWORK;
|
||||
}
|
||||
|
||||
Json::Reader jreader;
|
||||
Json::Value jret;
|
||||
|
|
|
@ -27,21 +27,11 @@ $app.create_controls = function (cb_stack) {
|
|||
dom_id: 'table-record',
|
||||
data_source: {
|
||||
type: 'ajax-post'
|
||||
,url: '/audit/get-records'
|
||||
, url: '/audit/get-records'
|
||||
//exclude: {'state': [TP_SESS_STAT_RUNNING, TP_SESS_STAT_STARTED]}
|
||||
},
|
||||
column_default: {sort: false, align: 'left'},
|
||||
columns: [
|
||||
// {
|
||||
// // title: '<input type="checkbox" id="user-list-select-all" value="">',
|
||||
// title: '<a href="javascript:;" data-reset-filter><i class="fa fa-rotate-left fa-fw"></i></a>',
|
||||
// key: 'chkbox',
|
||||
// sort: false,
|
||||
// width: 36,
|
||||
// align: 'center',
|
||||
// render: 'make_check_box',
|
||||
// fields: {id: 'id'}
|
||||
// },
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
|
@ -59,24 +49,17 @@ $app.create_controls = function (cb_stack) {
|
|||
{
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
//sort: true,
|
||||
//header_render: 'filter_search_host',
|
||||
render: 'user',
|
||||
fields: {user_username: 'user_username', user_surname: 'user_surname'}
|
||||
},
|
||||
{
|
||||
title: '来源',
|
||||
key: 'client_ip',
|
||||
//sort: true,
|
||||
//header_render: 'filter_search_host',
|
||||
//render: 'host_info',
|
||||
fields: {client_ip: 'client_ip'}
|
||||
},
|
||||
{
|
||||
title: '远程连接',
|
||||
key: 'remote',
|
||||
//sort: true,
|
||||
//header_render: 'filter_search_host',
|
||||
render: 'remote',
|
||||
fields: {acc_username: 'acc_username', host_ip: 'host_ip', conn_ip: 'conn_ip', conn_port: 'conn_port'}
|
||||
},
|
||||
|
@ -85,10 +68,6 @@ $app.create_controls = function (cb_stack) {
|
|||
key: 'protocol_type',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
// align: 'center',
|
||||
// width: 36,
|
||||
//sort: true
|
||||
// header_render: 'filter_os',
|
||||
render: 'protocol',
|
||||
fields: {protocol_type: 'protocol_type', protocol_sub_type: 'protocol_sub_type'}
|
||||
},
|
||||
|
@ -125,12 +104,12 @@ $app.create_controls = function (cb_stack) {
|
|||
render: 'record_action',
|
||||
fields: {id: 'id', state: 'state', time_end: 'time_end', protocol_sub_type: 'protocol_sub_type'}
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
// 重载回调函数
|
||||
on_header_created: $app.on_table_host_header_created,
|
||||
on_render_created: $app.on_table_host_render_created,
|
||||
on_cell_created: $app.on_table_host_cell_created
|
||||
//,on_header_created: $app.on_table_host_header_created
|
||||
, on_render_created: $app.on_table_host_render_created
|
||||
, on_cell_created: $app.on_table_host_cell_created
|
||||
};
|
||||
|
||||
$app.table_record = $tp.create_table(table_record_options);
|
||||
|
@ -141,10 +120,10 @@ $app.create_controls = function (cb_stack) {
|
|||
//-------------------------------
|
||||
// 用户列表相关过滤器
|
||||
//-------------------------------
|
||||
$tp.create_table_header_filter_search($app.table_record, {
|
||||
name: 'search',
|
||||
place_holder: '搜索:主机IP/名称/描述/资产编号/等等...'
|
||||
});
|
||||
// $tp.create_table_header_filter_search($app.table_record, {
|
||||
// name: 'search',
|
||||
// place_holder: '搜索:主机IP/名称/描述/资产编号/等等...'
|
||||
// });
|
||||
// $app.table_record_role_filter = $tp.create_table_filter_role($app.table_record, $app.role_list);
|
||||
// $tp.create_table_header_filter_state($app.table_record, 'state', $app.obj_states, [TP_STATE_LOCKED]);
|
||||
// 从cookie中读取用户分页限制的选择
|
||||
|
@ -168,11 +147,12 @@ $app.create_controls = function (cb_stack) {
|
|||
};
|
||||
|
||||
$app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||
if (col_key === 'chkbox') {
|
||||
cell_obj.find('[data-check-box]').click(function () {
|
||||
$app.check_host_all_selected();
|
||||
});
|
||||
} else if (col_key === 'action') {
|
||||
// if (col_key === 'chkbox') {
|
||||
// cell_obj.find('[data-check-box]').click(function () {
|
||||
// $app.check_host_all_selected();
|
||||
// });
|
||||
// } else
|
||||
if (col_key === 'action') {
|
||||
// 绑定系统选择框事件
|
||||
cell_obj.find('[data-action]').click(function () {
|
||||
|
||||
|
@ -183,7 +163,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
|||
if (action === 'replay') {
|
||||
//$app.dlg_edit_host.show_edit(row_id);
|
||||
if (row_data.protocol_type === TP_PROTOCOL_TYPE_RDP) {
|
||||
$tp.notify_error('sorry, not impl.');
|
||||
// $tp.notify_error('sorry, not impl.');
|
||||
$app.do_replay_rdp(row_data.id, row_data.user_username, row_data.acc_username, row_data.host_ip, row_data.time_begin);
|
||||
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) {
|
||||
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
||||
}
|
||||
|
@ -206,36 +187,36 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
|||
};
|
||||
|
||||
$app.on_table_host_render_created = function (render) {
|
||||
render.filter_host_state = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
_ret.push('<div class="tp-table-filter-inner">');
|
||||
_ret.push('<div class="search-title">' + title + '</div>');
|
||||
// render.filter_host_state = function (header, title, col) {
|
||||
// var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
// _ret.push('<div class="tp-table-filter-inner">');
|
||||
// _ret.push('<div class="search-title">' + title + '</div>');
|
||||
//
|
||||
// // 表格内嵌过滤器的DOM实体在这时生成
|
||||
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
|
||||
// _ret.push(filter_ctrl.render());
|
||||
//
|
||||
// _ret.push('</div></div>');
|
||||
//
|
||||
// return _ret.join('');
|
||||
// };
|
||||
//
|
||||
// render.filter_search_host = function (header, title, col) {
|
||||
// var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
|
||||
// _ret.push('<div class="tp-table-filter-inner">');
|
||||
// _ret.push('<div class="search-title">' + title + '</div>');
|
||||
//
|
||||
// // 表格内嵌过滤器的DOM实体在这时生成
|
||||
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
|
||||
// _ret.push(filter_ctrl.render());
|
||||
//
|
||||
// _ret.push('</div></div>');
|
||||
//
|
||||
// return _ret.join('');
|
||||
// };
|
||||
|
||||
// 表格内嵌过滤器的DOM实体在这时生成
|
||||
var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
||||
return _ret.join('');
|
||||
};
|
||||
|
||||
render.filter_search_host = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
|
||||
_ret.push('<div class="tp-table-filter-inner">');
|
||||
_ret.push('<div class="search-title">' + title + '</div>');
|
||||
|
||||
// 表格内嵌过滤器的DOM实体在这时生成
|
||||
var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
||||
return _ret.join('');
|
||||
};
|
||||
|
||||
render.sid = function(row_id, fields) {
|
||||
return '<span class="mono">'+fields.sid+'</span>';
|
||||
render.sid = function (row_id, fields) {
|
||||
return '<span class="mono">' + fields.sid + '</span>';
|
||||
};
|
||||
|
||||
render.user = function (row_id, fields) {
|
||||
|
@ -270,7 +251,6 @@ $app.on_table_host_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.time_begin = function (row_id, fields) {
|
||||
// return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
|
||||
return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
|
||||
};
|
||||
|
||||
|
@ -373,60 +353,84 @@ $app.on_table_host_render_created = function (render) {
|
|||
};
|
||||
};
|
||||
|
||||
$app.on_table_host_header_created = function (header) {
|
||||
$('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
|
||||
CALLBACK_STACK.create()
|
||||
.add(header._table_ctrl.load_data)
|
||||
.add(header._table_ctrl.reset_filters)
|
||||
.exec();
|
||||
});
|
||||
|
||||
// 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
|
||||
header._table_ctrl.get_filter_ctrl('search').on_created();
|
||||
};
|
||||
|
||||
$app.get_selected_record = function (tbl) {
|
||||
var records = [];
|
||||
var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
|
||||
$.each(_objs, function (i, _obj) {
|
||||
if ($(_obj).is(':checked')) {
|
||||
var _row_data = tbl.get_row(_obj);
|
||||
records.push(_row_data.id);
|
||||
$app.do_replay_rdp = function (record_id, user_username, acc_username, host_ip, time_begin) {
|
||||
$assist.do_rdp_replay(
|
||||
{
|
||||
rid: record_id
|
||||
// , web: $tp.web_server // + '/audit/get_rdp_record/' + record_id // 'http://' + ip + ':' + port + '/log/replay/rdp/' + record_id;
|
||||
// , sid: Cookies.get('_sid')
|
||||
, user: user_username
|
||||
, acc: acc_username
|
||||
, host: host_ip
|
||||
, start: time_begin//tp_format_datetime(tp_utc2local(time_begin), 'yyyyMMdd-HHmmss')
|
||||
}
|
||||
});
|
||||
return records;
|
||||
, function () {
|
||||
// func_success
|
||||
}
|
||||
, function (code, message) {
|
||||
if (code === TPE_NO_ASSIST)
|
||||
$assist.alert_assist_not_found();
|
||||
else
|
||||
$tp.notify_error('播放RDP操作录像失败:' + tp_error_msg(code, message));
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$app.on_btn_remove_record_click = function () {
|
||||
// var records = $app.get_selected_record($app.table_record);
|
||||
// if (records.length === 0) {
|
||||
// $tp.notify_error('请选择要删除的会话记录!');
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var _fn_sure = function (cb_stack, cb_args) {
|
||||
// $tp.ajax_post_json('/user/remove-user', {users: users},
|
||||
// function (ret) {
|
||||
// if (ret.code === TPE_OK) {
|
||||
// cb_stack.add($app.check_host_all_selected);
|
||||
// cb_stack.add($app.table_record.load_data);
|
||||
// $tp.notify_success('删除用户账号操作成功!');
|
||||
// } else {
|
||||
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message));
|
||||
// }
|
||||
//
|
||||
// cb_stack.exec();
|
||||
// },
|
||||
// function () {
|
||||
// $tp.notify_error('网络故障,删除用户账号操作失败!');
|
||||
// cb_stack.exec();
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
//
|
||||
// var cb_stack = CALLBACK_STACK.create();
|
||||
// $tp.dlg_confirm(cb_stack, {
|
||||
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>',
|
||||
// fn_yes: _fn_sure
|
||||
// });
|
||||
};
|
||||
|
||||
// $app.on_table_host_header_created = function (header) {
|
||||
// $('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
|
||||
// CALLBACK_STACK.create()
|
||||
// .add(header._table_ctrl.load_data)
|
||||
// .add(header._table_ctrl.reset_filters)
|
||||
// .exec();
|
||||
// });
|
||||
//
|
||||
// // 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
|
||||
// header._table_ctrl.get_filter_ctrl('search').on_created();
|
||||
// };
|
||||
|
||||
// $app.get_selected_record = function (tbl) {
|
||||
// var records = [];
|
||||
// var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
|
||||
// $.each(_objs, function (i, _obj) {
|
||||
// if ($(_obj).is(':checked')) {
|
||||
// var _row_data = tbl.get_row(_obj);
|
||||
// records.push(_row_data.id);
|
||||
// }
|
||||
// });
|
||||
// return records;
|
||||
// };
|
||||
|
||||
// $app.on_btn_remove_record_click = function () {
|
||||
// var records = $app.get_selected_record($app.table_record);
|
||||
// if (records.length === 0) {
|
||||
// $tp.notify_error('请选择要删除的会话记录!');
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var _fn_sure = function (cb_stack, cb_args) {
|
||||
// $tp.ajax_post_json('/user/remove-user', {users: users},
|
||||
// function (ret) {
|
||||
// if (ret.code === TPE_OK) {
|
||||
// cb_stack.add($app.check_host_all_selected);
|
||||
// cb_stack.add($app.table_record.load_data);
|
||||
// $tp.notify_success('删除用户账号操作成功!');
|
||||
// } else {
|
||||
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message));
|
||||
// }
|
||||
//
|
||||
// cb_stack.exec();
|
||||
// },
|
||||
// function () {
|
||||
// $tp.notify_error('网络故障,删除用户账号操作失败!');
|
||||
// cb_stack.exec();
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
//
|
||||
// var cb_stack = CALLBACK_STACK.create();
|
||||
// $tp.dlg_confirm(cb_stack, {
|
||||
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>',
|
||||
// fn_yes: _fn_sure
|
||||
// });
|
||||
// };
|
||||
|
|
|
@ -53,13 +53,11 @@ var CALLBACK_STACK = {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// console.log(window.location, window.location.protocol+'://'+window.location.host);
|
||||
|
||||
|
||||
// Teleport核心JS
|
||||
var $tp = {
|
||||
web_server: window.location.protocol+'://'+window.location.host
|
||||
web_server: window.location.protocol+'//'+window.location.host
|
||||
|
||||
// Teleport页面应用对象,放置页面自身特有的属性和函数
|
||||
, app: {
|
||||
|
@ -79,28 +77,6 @@ $tp.init = function () {
|
|||
{id: TP_STATE_LOCKED, name: '临时锁定', style: 'warning'}
|
||||
];
|
||||
|
||||
// $app.user_states = [
|
||||
// {id: 1, name: '正常', style: 'success'},
|
||||
// {id: 2, name: '临时锁定', style: 'warning'},
|
||||
// {id: 3, name: '禁用', style: 'danger'}
|
||||
// ];
|
||||
//
|
||||
// $app.acc_states = [
|
||||
// {id: 1, name: '正常', style: 'success'},
|
||||
// {id: 2, name: '临时锁定', style: 'warning'},
|
||||
// {id: 3, name: '禁用', style: 'danger'}
|
||||
// ];
|
||||
//
|
||||
// $app.host_states = [
|
||||
// {id: 1, name: '正常', style: 'success'},
|
||||
// {id: 2, name: '禁用', style: 'danger'}
|
||||
// ];
|
||||
//
|
||||
// $app.policy_states = [
|
||||
// {id: 1, name: '正常', style: 'success'},
|
||||
// {id: 2, name: '禁用', style: 'danger'}
|
||||
// ];
|
||||
|
||||
$app.host_types = [
|
||||
{id: 1, name: '物理主机', style: 'success'},
|
||||
{id: 2, name: '虚拟主机', style: 'info'},
|
||||
|
|
|
@ -839,7 +839,8 @@ $tp.create_table_header = function (tbl, on_created) {
|
|||
|
||||
if (_.isFunction(on_created))
|
||||
on_created(_tbl_header);
|
||||
else if (!_.isUndefined(on_created))
|
||||
//else if (!_.isUndefined(on_created))
|
||||
else if (!_.isNull(on_created))
|
||||
console.error('create table header, on_created() is not callable.');
|
||||
|
||||
cb_stack.exec();
|
||||
|
|
|
@ -27,7 +27,7 @@ $assist.init = function (cb_stack) {
|
|||
$assist.running = true;
|
||||
$assist.version = ret.version;
|
||||
|
||||
if(_.isFunction($tp.assist_checked)) {
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
// if (version_compare()) {
|
||||
|
@ -38,7 +38,7 @@ $assist.init = function (cb_stack) {
|
|||
},
|
||||
error: function () {
|
||||
$assist.running = false;
|
||||
if(_.isFunction($tp.assist_checked)) {
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
// func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||
|
@ -120,7 +120,7 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
|||
jsonp: 'callback',
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
if(ret.code === TPE_OK) {
|
||||
if (ret.code === TPE_OK) {
|
||||
func_success();
|
||||
} else {
|
||||
func_error(ret.code, ret.message);
|
||||
|
@ -144,6 +144,45 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
|||
});
|
||||
};
|
||||
|
||||
$assist.do_rdp_replay = function (args, func_success, func_error) {
|
||||
// ==================================================
|
||||
// args is dict with fields shown below:
|
||||
// rid: (int) - record-id in database.
|
||||
// user: (string) - who did the RDP connection.
|
||||
// acc: (string) - account to login to remote RDP server.
|
||||
// host: (string) - IP of the remote RDP server.
|
||||
// start: (string) - when start the RDP connection, should be a UTC timestamp.
|
||||
// ==================================================
|
||||
|
||||
// now fix the args.
|
||||
args.web = $tp.web_server; // (string) - teleport server base address, like "http://127.0.0.1:7190", without end-slash.
|
||||
args.sid = Cookies.get('_sid'); // (string) - current login user's session-id.
|
||||
args.start = tp_format_datetime(tp_utc2local(args.start), 'yyyyMMdd-HHmmss'); // (string) - convert UTC timestamp to local human-readable string.
|
||||
|
||||
console.log('do-rdp-replay:', args);
|
||||
|
||||
var args_ = encodeURIComponent(JSON.stringify(args));
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 6000,
|
||||
url: $assist.api_url + '/rdp_play/' + args_,
|
||||
jsonp: 'callback',
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
console.log('ret', ret);
|
||||
if (ret.code === TPE_OK) {
|
||||
func_success();
|
||||
} else {
|
||||
// func_error(ret.code, '查看远程桌面操作录像失败!');
|
||||
func_error(ret.code, ret.message);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
func_error(TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
var version_compare = function () {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<%inherit file="../page_base.mako"/>
|
||||
|
||||
<%block name="extend_js_file">
|
||||
<script type="text/javascript" src="${ static_url('js/tp-assist.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('js/audit/record-list.js') }"></script>
|
||||
</%block>
|
||||
|
||||
|
|
|
@ -183,6 +183,9 @@ controllers = [
|
|||
# - [json] 读取录像数据
|
||||
(r'/audit/get-record-data', audit.DoGetRecordDataHandler),
|
||||
|
||||
# - 读取录像文件(用于RDP录像回放)
|
||||
(r'/audit/get-file', audit.DoGetFileHandler),
|
||||
|
||||
# (r'/host/export-host', host.ExportHostHandler),
|
||||
# (r'/config/export-database', config.ExportDatabaseHandler),
|
||||
# (r'/config/import-database', config.ImportDatabaseHandler),
|
||||
|
|
|
@ -274,3 +274,82 @@ class DoGetRecordDataHandler(TPBaseJsonHandler):
|
|||
|
||||
data_list, data_size, err = record.read_record_data(record_id, offset)
|
||||
self.write_json(err, data={'data_list': data_list, 'data_size': data_size})
|
||||
|
||||
|
||||
class DoGetFileHandler(TPBaseHandler):
|
||||
@tornado.gen.coroutine
|
||||
def get(self):
|
||||
|
||||
log.v('--{}\n'.format(self.request.uri))
|
||||
|
||||
require_privilege = TP_PRIVILEGE_OPS | TP_PRIVILEGE_OPS_AUZ | TP_PRIVILEGE_AUDIT_AUZ | TP_PRIVILEGE_AUDIT_OPS_HISTORY
|
||||
|
||||
# sid = self.get_argument('sid', None)
|
||||
# if sid is None:
|
||||
# self.set_status(403)
|
||||
# return self.write('need login first.')
|
||||
#
|
||||
# self._s_id = sid
|
||||
# _user = self.get_session('user')
|
||||
# if _user is None:
|
||||
# self.set_status(403)
|
||||
# return self.write('need login first.')
|
||||
# self._user = _user
|
||||
|
||||
if not self._user['_is_login']:
|
||||
self.set_status(401) # 401=未授权, 要求身份验证
|
||||
return self.write('need login first.')
|
||||
if (self._user['privilege'] & require_privilege) == 0:
|
||||
self.set_status(403) # 403=禁止
|
||||
return self.write('you have no such privilege.')
|
||||
|
||||
act = self.get_argument('act', None)
|
||||
_type = self.get_argument('type', None)
|
||||
rid = self.get_argument('rid', None)
|
||||
filename = self.get_argument('f', None)
|
||||
offset = int(self.get_argument('offset', '0'))
|
||||
length = int(self.get_argument('length', '-1')) # -1 means read all content.
|
||||
if act is None or _type is None or rid is None or filename is None:
|
||||
self.set_status(400) # 400=错误请求
|
||||
return self.write('invalid param, `rid` and `f` must present.')
|
||||
|
||||
if act not in ['size', 'read']:
|
||||
self.set_status(400)
|
||||
return self.write('invalid param, `act` should be `size` or `read`.')
|
||||
if _type not in ['rdp', 'ssh', 'telnet']:
|
||||
self.set_status(400)
|
||||
return self.write('invalid param, `type` should be `rdp`, `ssh` or `telnet`.')
|
||||
|
||||
file = os.path.join(get_cfg().core.replay_path, 'rdp', '{:09d}'.format(int(rid)), filename)
|
||||
if not os.path.exists(file):
|
||||
self.set_status(404)
|
||||
return self.write('file does not exists.')
|
||||
|
||||
file_size = os.path.getsize(file)
|
||||
|
||||
if act == 'size':
|
||||
log.d('--return size:{}\n'.format(file_size))
|
||||
return self.write('{}'.format(file_size))
|
||||
|
||||
if offset >= file_size:
|
||||
self.set_status(416) # 416=请求范围不符合要求
|
||||
return self.write('no more data.')
|
||||
|
||||
# we read most 4096 bytes one time.
|
||||
BULK_SIZE = 4096
|
||||
total_need = file_size - offset
|
||||
if length != -1 and length < total_need:
|
||||
total_need = length
|
||||
total_read = 0
|
||||
with open(file, 'rb') as f:
|
||||
f.seek(offset)
|
||||
read_this_time = BULK_SIZE if total_need > BULK_SIZE else total_need
|
||||
while read_this_time > 0:
|
||||
self.write(f.read(read_this_time))
|
||||
total_read += read_this_time
|
||||
if total_read >= total_need:
|
||||
break
|
||||
read_left = total_need - total_read
|
||||
read_this_time = BULK_SIZE if read_left > BULK_SIZE else read_left
|
||||
|
||||
# all need data read.
|
||||
|
|
Loading…
Reference in New Issue