配置远程账号时可以不设置密码,让用户在进行远程连接时手动输入。

feature/assist-websocket
Apex Liu 2022-05-29 03:46:34 +08:00
parent fef0e95846
commit 5c286811c9
35 changed files with 827 additions and 517 deletions

View File

@ -21,7 +21,7 @@
"name": "securecrt", "name": "securecrt",
"display": "SecureCRT", "display": "SecureCRT",
"app": "/Applications/SecureCRT.app/Contents/MacOS/SecureCRT", "app": "/Applications/SecureCRT.app/Contents/MacOS/SecureCRT",
"cmdline": "/T /N \"TP#ssh://{real_ip}\" /SSH2 /L {user_name} /PASSWORD **** {host_ip}:{host_port}", "cmdline": "/T /N \"TP#ssh://{real_ip}\" /SSH2 /L {user_name} {password:/PASSWORD ****} {host_ip}:{host_port}",
"desc": [] "desc": []
}, },
{ {
@ -41,14 +41,14 @@
"name": "securefx", "name": "securefx",
"display": "SecureFX", "display": "SecureFX",
"app": "/Applications/SecureFX.app/Contents/MacOS/SecureFX", "app": "/Applications/SecureFX.app/Contents/MacOS/SecureFX",
"cmdline": "sftp://{user_name}:****@{host_ip}:{host_port}", "cmdline": "sftp://{user_name}{password::****}@{host_ip}:{host_port}",
"desc": [] "desc": []
}, },
{ {
"name": "filezilla", "name": "filezilla",
"display": "FileZilla", "display": "FileZilla",
"app": "/Applications/FileZilla.app/Contents/MacOS/filezilla", "app": "/Applications/FileZilla.app/Contents/MacOS/filezilla",
"cmdline": "sftp://{user_name}:****@{host_ip}:{host_port}", "cmdline": "{interactive:-l ask} sftp://{user_name}{password::****}@{host_ip}:{host_port}",
"desc": [] "desc": []
}, },
{ {

View File

@ -6,28 +6,28 @@
"name": "putty", "name": "putty",
"display": "PuTTY内置", "display": "PuTTY内置",
"app": "{assist_tools_path}\\putty\\putty.exe", "app": "{assist_tools_path}\\putty\\putty.exe",
"cmdline": "-ssh -pw **** -P {host_port} -l {user_name} {host_ip}", "cmdline": "-ssh {password:-pw ****} -P {host_port} -l {user_name} {host_ip}",
"desc": [] "desc": []
}, },
{ {
"name": "crt", "name": "crt",
"display": "SecureCRT", "display": "SecureCRT",
"app": "", "app": "",
"cmdline": "/T /N \"TP#ssh://{real_ip}\" /SSH2 /P {host_port} /PASSWORD **** {user_name}@{host_ip}", "cmdline": "/T /N \"TP#ssh://{real_ip}\" /SSH2 /P {host_port} {password:/PASSWORD ****} {user_name}@{host_ip}",
"desc": [] "desc": []
}, },
{ {
"name": "xshell", "name": "xshell",
"display": "Xshell", "display": "Xshell",
"app": "", "app": "",
"cmdline": "-newtab \"TP#ssh://{real_ip}\" -url ssh://{user_name}:****@{host_ip}:{host_port}", "cmdline": "-newtab \"TP#ssh://{real_ip}\" -url ssh://{user_name}{password::****}@{host_ip}:{host_port}",
"desc": [] "desc": []
}, },
{ {
"name": "mobaxterm", "name": "mobaxterm",
"display": "MobaXterm", "display": "MobaXterm",
"app": "", "app": "",
"cmdline": "-newtab \"sshpass -p**** ssh {user_name}@{host_ip} -p {host_port}\"", "cmdline": "-newtab \"sshpass {password:-p****} ssh {user_name}@{host_ip} -p {host_port}\"",
"desc": [] "desc": []
}, },
{ {
@ -45,7 +45,7 @@
"name": "winscp", "name": "winscp",
"display": "WinSCP内置", "display": "WinSCP内置",
"app": "{assist_tools_path}\\winscp\\winscp.exe", "app": "{assist_tools_path}\\winscp\\winscp.exe",
"cmdline": "/sessionname=\"TP#{real_ip}\" {user_name}:****@{host_ip}:{host_port}", "cmdline": "/sessionname=\"TP#{real_ip}\" {user_name}{password::****}@{host_ip}:{host_port}",
"desc": [] "desc": []
}, },
{ {

View File

@ -1,11 +1,11 @@
on scriptRun(argsCmd, argsProfile, argsTitle) on scriptRun(argsCmd, argsProfile, argsTitle, argsInteractiveMode)
set theCmd to (argsCmd) set theCmd to (argsCmd)
set theProfile to (argsProfile) set theProfile to (argsProfile)
set theTitle to (argsTitle) set theTitle to (argsTitle)
CommandRun(theCmd, theProfile, theTitle) CommandRun(theCmd, theProfile, theTitle, argsInteractiveMode)
end scriptRun end scriptRun
on CommandRun(theCmd, theProfile, theTitle) on CommandRun(theCmd, theProfile, theTitle, theInteractiveMode)
try try
tell application "iTerm" tell application "iTerm"
if it is not running then if it is not running then
@ -29,8 +29,10 @@ on CommandRun(theCmd, theProfile, theTitle)
set name to theTitle set name to theTitle
set profile to theProfile set profile to theProfile
write text theCmd write text theCmd
delay 0.5 if theInteractiveMode = "no" then
write text "" delay 0.5
write text ""
end if
end tell end tell
end tell end tell
end tell end tell
@ -50,8 +52,10 @@ on CommandRun(theCmd, theProfile, theTitle)
delay 0.5 delay 0.5
set name to theTitle set name to theTitle
write text theCmd write text theCmd
delay 0.5 if theInteractiveMode = "no" then
write text "" delay 0.5
write text ""
end if
end tell end tell
end tell end tell
end tell end tell
@ -70,8 +74,10 @@ on CommandRun(theCmd, theProfile, theTitle)
delay 0.5 delay 0.5
set name to theTitle set name to theTitle
write text theCmd write text theCmd
delay 0.5 if theInteractiveMode = "no" then
write text "" delay 0.5
write text ""
end if
end tell end tell
end tell end tell
end tell end tell

View File

@ -1,26 +1,29 @@
on scriptRun(argsCmd, argsProfile, argsTitle) on scriptRun(argsCmd, argsProfile, argsTitle, argsInteractiveMode)
set theCmd to (argsCmd) set theCmd to (argsCmd)
set theProfile to (argsProfile) set theProfile to (argsProfile)
set theTitle to (argsTitle) set theTitle to (argsTitle)
CommandRun(theCmd, theProfile, theTitle) CommandRun(theCmd, theProfile, theTitle, argsInteractiveMode)
end scriptRun end scriptRun
on CommandRun(theCmd, theProfile, theTitle) on CommandRun(theCmd, theProfile, theTitle, theInteractiveMode)
try try
tell application "Terminal" tell application "Terminal"
if it is not running then if it is not running then
--if this is the first time Terminal is running you have specify window 1 --if this is the first time Terminal is running you have specify window 1
--if you dont do this you will get two windows and the title wont be set --if you dont do this you will get two windows and the title wont be set
activate activate
delay 3.0 delay 3.0
set newTerm to do script theCmd in window 1 set newTerm to do script theCmd in window 1
set newTerm's current settings to settings set theProfile
set newTerm's current settings to settings set theProfile
set custom title of front window to theTitle set custom title of front window to theTitle
delay 1.0 if theInteractiveMode = "no"
reopen delay 1.0
activate reopen
tell application "System Events" to key code 36 activate
tell application "System Events" to key code 36
end if
else else
--Terminal is running get the window count --Terminal is running get the window count
set windowCount to (count every window) set windowCount to (count every window)
@ -36,21 +39,21 @@ on CommandRun(theCmd, theProfile, theTitle)
set title displays custom title of front window to true set title displays custom title of front window to true
set custom title of selected tab of front window to theTitle set custom title of selected tab of front window to theTitle
delay 1.0 if theInteractiveMode = "no"
reopen delay 1.0
activate reopen
tell application "System Events" to key code 36 activate
tell application "System Events" to key code 36
end if
else else
--Terminal is running and we have a window run in a new tab --Terminal is running and we have a window run in a new tab
delay 1.0
reopen reopen
activate activate
tell application "System Events" tell application "System Events"
tell process "Terminal" -- Command+T = new tab.
delay 0.5 key code 17 using {command down}
keystroke "t" using {command down}
end tell
end tell end tell
reopen reopen
@ -61,16 +64,14 @@ on CommandRun(theCmd, theProfile, theTitle)
set title displays custom title of front window to true set title displays custom title of front window to true
set custom title of selected tab of front window to theTitle set custom title of selected tab of front window to theTitle
delay 1.0 if theInteractiveMode = "no"
reopen delay 1.0
activate reopen
tell application "System Events" to key code 36 activate
tell application "System Events" to key code 36
end if
end if end if
--set current settings of selected tab of front window to settings set theProfile
--set title displays custom title of front window to true
--set custom title of selected tab of front window to theTitle
end if end if
end tell end tell

View File

@ -12,7 +12,7 @@
extern void* g_app; extern void* g_app;
int AppDelegate_start_ssh_client (void *_self, const char* cmd_line, const char* term_type, const char* term_theme, const char* term_title); int AppDelegate_start_ssh_client (void *_self, const char* cmd_line, const char* term_type, const char* term_theme, const char* term_title, const char* interactive_mode);
int AppDelegate_select_app (void *_self); int AppDelegate_select_app (void *_self);
// for cpp global object initialize. // for cpp global object initialize.

View File

@ -29,13 +29,14 @@
@implementation AppDelegate @implementation AppDelegate
int AppDelegate_start_ssh_client (void *_self, const char* cmd_line, const char* term_type, const char* term_theme, const char* term_title) { int AppDelegate_start_ssh_client (void *_self, const char* cmd_line, const char* term_type, const char* term_theme, const char* term_title, const char* interactive_mode) {
NSString* cmdLine = [NSString stringWithUTF8String:cmd_line]; NSString* cmdLine = [NSString stringWithUTF8String:cmd_line];
NSString* termType = [NSString stringWithUTF8String:term_type]; NSString* termType = [NSString stringWithUTF8String:term_type];
NSString* termTheme = [NSString stringWithUTF8String:term_theme]; NSString* termTheme = [NSString stringWithUTF8String:term_theme];
NSString* termTitle = [NSString stringWithUTF8String:term_title]; NSString* termTitle = [NSString stringWithUTF8String:term_title];
NSString* interactiveMode = [NSString stringWithUTF8String:interactive_mode];
return [(__bridge id)_self start_ssh_client:cmdLine termType:termType termTheme:termTheme termTitle:termTitle]; return [(__bridge id)_self start_ssh_client:cmdLine termType:termType termTheme:termTheme termTitle:termTitle interactiveMode:interactiveMode];
} }
int AppDelegate_select_app (void *_self) { int AppDelegate_select_app (void *_self) {
@ -118,14 +119,14 @@ int AppDelegate_select_app (void *_self) {
} }
} }
- (int) start_ssh_client:(NSString*)cmd_line termType:(NSString*)term_type termTheme:(NSString*)term_theme termTitle:(NSString*)term_title { - (int) start_ssh_client:(NSString*)cmd_line termType:(NSString*)term_type termTheme:(NSString*)term_theme termTitle:(NSString*)term_title interactiveMode:(NSString*)interactive_mode {
NSString *term = [[NSBundle mainBundle] pathForResource:term_type ofType:@"scpt"]; NSString *term = [[NSBundle mainBundle] pathForResource:term_type ofType:@"scpt"];
if(!term) if(!term)
return 1; return 1;
NSString *handlerName = @"scriptRun"; NSString *handlerName = @"scriptRun";
NSArray *passParameters = @[cmd_line, term_theme, term_title]; NSArray *passParameters = @[cmd_line, term_theme, term_title, interactive_mode];
[self runScript:term handler:handlerName parameters:passParameters]; [self runScript:term handler:handlerName parameters:passParameters];
return 0; return 0;

View File

@ -181,9 +181,9 @@ void TsWsClient::_process_replay_rdp(const std::string& param, Json::Value& js_r
// ============================================================================ // ============================================================================
TsWsClient::TsWsClient() : TsWsClient::TsWsClient() :
ExThreadBase("ws-client-thread"), ExThreadBase("ws-client-thread"),
m_nc(NULL), m_nc(NULL),
m_assist_id(0) m_assist_id(0)
{ {
mg_mgr_init(&m_mg_mgr, NULL); mg_mgr_init(&m_mg_mgr, NULL);
} }
@ -215,8 +215,8 @@ void TsWsClient::_register(const std::string& ws_url, uint32_t assist_id, const
// //
char msg[256] = {0}; char msg[256] = {0};
ex_strformat( ex_strformat(
msg, 256, "{\"type\":0,\"method\":\"register\",\"param\":{\"client\":\"assist\",\"sid\":\"%s\",\"request_assist_id\":%u,\"assist_id\":%u,\"assist_ver\":\"%s\"}}", msg, 256, "{\"type\":0,\"method\":\"register\",\"param\":{\"client\":\"assist\",\"sid\":\"%s\",\"request_assist_id\":%u,\"assist_id\":%u,\"assist_ver\":\"%s\"}}",
session_id.c_str(), assist_id, m_assist_id, a_ver.c_str()); session_id.c_str(), assist_id, m_assist_id, a_ver.c_str());
if (!m_is_running) if (!m_is_running)
{ {
@ -253,57 +253,57 @@ void TsWsClient::_mg_event_handler(struct mg_connection* nc, int ev, void* ev_da
switch (ev) switch (ev)
{ {
case MG_EV_CONNECT: case MG_EV_CONNECT:
{
int status = *((int*)ev_data);
if (status != 0)
{ {
EXLOGE("[ERROR] -- connect to ws server failed: %d\n", status); int status = *((int*)ev_data);
if (status != 0)
{
EXLOGE("[ERROR] -- connect to ws server failed: %d\n", status);
}
break;
} }
break; case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
}
case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
{
auto* hm = (struct http_message*)ev_data;
if (hm->resp_code == 101)
{ {
EXLOGV("-- ws server connected\n"); auto* hm = (struct http_message*)ev_data;
} if (hm->resp_code == 101)
else {
{ EXLOGV("-- ws server connected\n");
EXLOGE("[ERROR] -- connect to ws server failed, HTTP code: %d\n", hm->resp_code); }
} else
break; {
} EXLOGE("[ERROR] -- connect to ws server failed, HTTP code: %d\n", hm->resp_code);
}
break;
case MG_EV_WEBSOCKET_FRAME:
{
// on_message().
auto* wm = (struct websocket_message*)ev_data;
// EXLOGV("%d: %s\n", wm->size, wm->data);
std::string message;
message.assign((const char*)wm->data, wm->size);
std::string buf;
_this->_on_message(message, buf);
if (!buf.empty())
{
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, buf.c_str(), buf.length());
} }
break;
} case MG_EV_WEBSOCKET_FRAME:
{
// on_message().
auto* wm = (struct websocket_message*)ev_data;
// EXLOGV("%d: %s\n", wm->size, wm->data);
std::string message;
message.assign((const char*)wm->data, wm->size);
std::string buf;
_this->_on_message(message, buf);
if (!buf.empty())
{
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, buf.c_str(), buf.length());
}
break;
}
case MG_EV_CLOSE: case MG_EV_CLOSE:
{ {
EXLOGV("-- ws server disconnected\n"); EXLOGV("-- ws server disconnected\n");
_this->m_need_stop = true; _this->m_need_stop = true;
break; break;
} }
} }
} }
@ -488,7 +488,7 @@ void TsWsClient::_rpc_func_replay_rdp(ex_astr& buf, AssistMessage& msg_req, Json
if (!js_param["rid"].isNumeric() if (!js_param["rid"].isNumeric()
|| !js_param["web"].isString() || !js_param["web"].isString()
|| !js_param["sid"].isString() || !js_param["sid"].isString()
) )
{ {
_create_response(buf, msg_req, TPE_PARAM); _create_response(buf, msg_req, TPE_PARAM);
return; return;
@ -586,12 +586,25 @@ void TsWsClient::_rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json
|| !js_param["teleport_port"].isNumeric() || !js_param["remote_host_ip"].isString() || !js_param["teleport_port"].isNumeric() || !js_param["remote_host_ip"].isString()
|| !js_param["session_id"].isString() || !js_param["protocol_type"].isNumeric() || !js_param["protocol_sub_type"].isNumeric() || !js_param["session_id"].isString() || !js_param["protocol_type"].isNumeric() || !js_param["protocol_sub_type"].isNumeric()
|| !js_param["protocol_flag"].isNumeric() || !js_param["protocol_flag"].isNumeric()
) )
{ {
_create_response(buf, msg_req, TPE_PARAM); _create_response(buf, msg_req, TPE_PARAM);
return; return;
} }
const char* interactive_mode = "no";
bool is_interactive_mode = false;
if(!js_param["is_interactive"].isNull()) {
if(!js_param["is_interactive"].isBool()) {
_create_response(buf, msg_req, TPE_PARAM);
return;
}
if(js_param["is_interactive"].asBool()) {
interactive_mode = "yes";
is_interactive_mode = true;
}
}
int pro_type = js_param["protocol_type"].asUInt(); int pro_type = js_param["protocol_type"].asUInt();
int pro_sub = js_param["protocol_sub_type"].asInt(); int pro_sub = js_param["protocol_sub_type"].asInt();
ex_u32 protocol_flag = js_param["protocol_flag"].asUInt(); ex_u32 protocol_flag = js_param["protocol_flag"].asUInt();
@ -785,7 +798,7 @@ void TsWsClient::_rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json
char szTitle[128] = {0}; char szTitle[128] = {0};
ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str()); ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str());
int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.ssh.name.c_str(), g_cfg.ssh.cmdline.c_str(), szTitle); int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.ssh.name.c_str(), g_cfg.ssh.cmdline.c_str(), szTitle, interactive_mode);
if (ret == 0) if (ret == 0)
_create_response(buf, msg_req, TPE_OK); _create_response(buf, msg_req, TPE_OK);
else else
@ -843,7 +856,7 @@ void TsWsClient::_rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json
char szTitle[128] = {0}; char szTitle[128] = {0};
ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str()); ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str());
int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.telnet.name.c_str(), g_cfg.telnet.cmdline.c_str(), szTitle); int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.telnet.name.c_str(), g_cfg.telnet.cmdline.c_str(), szTitle, interactive_mode);
if (ret == 0) if (ret == 0)
_create_response(buf, msg_req, TPE_OK); _create_response(buf, msg_req, TPE_OK);
else else
@ -863,11 +876,61 @@ void TsWsClient::_rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json
s_arg = g_cfg.telnet.cmdline; s_arg = g_cfg.telnet.cmdline;
} }
//---- split s_arg and push to s_argv --- //---- split s_arg and push to s_argv ---
ex_astr::size_type p1 = 0; ex_astr::size_type p1 = 0;
ex_astr::size_type p2 = 0; ex_astr::size_type p2 = 0;
ex_astr tmp = s_arg; ex_astr tmp;
for(;;){
p1 = s_arg.find("{password:");
if(p1 != ex_astr::npos) {
p2 = s_arg.find('}', p1+10);
if(p2 == ex_astr::npos) {
_create_response(buf, msg_req, TPE_PARAM);
return;
}
if(is_interactive_mode) {
// 如果需要用户自己输入密码,则客户端命令行就不能带密码字段,需要抹去这个参数
s_arg.erase(p1, p2-p1+1);
}
else{
s_arg.erase(p2, 1);
s_arg.erase(p1, 10);
}
}
else
{
break;
}
}
for(;;){
p1 = s_arg.find("{interactive:");
if(p1 != ex_astr::npos) {
p2 = s_arg.find('}', p1+13);
if(p2 == ex_astr::npos) {
_create_response(buf, msg_req, TPE_PARAM);
return;
}
if(!is_interactive_mode) {
// 如果无需用户自己输入密码,则需要抹去这个参数
s_arg.erase(p1, p2-p1+1);
}
else{
s_arg.erase(p2, 1);
s_arg.erase(p1, 13);
}
}
else
{
break;
}
}
tmp = s_arg;
for (;;) for (;;)
{ {
ex_remove_white_space(tmp, EX_RSC_BEGIN); ex_remove_white_space(tmp, EX_RSC_BEGIN);

View File

@ -440,7 +440,7 @@ void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf)
is_enc = false; is_enc = false;
plain_text = json_param["p"].asCString(); plain_text = json_param["p"].asCString();
if (plain_text.length() == 0) if (plain_text.empty())
{ {
_create_json_ret(buf, TPE_PARAM); _create_json_ret(buf, TPE_PARAM);
return; return;

View File

@ -4,6 +4,9 @@
#include <mbedtls/sha1.h> #include <mbedtls/sha1.h>
#include <teleport_const.h> #include <teleport_const.h>
// 临时会话ID有效期毫秒
#define TEMP_SESSION_ID_VALID_TIME 60000
TsSessionManager g_session_mgr; TsSessionManager g_session_mgr;
TsSessionManager::TsSessionManager() : TsSessionManager::TsSessionManager() :
@ -44,7 +47,7 @@ void TsSessionManager::_remove_expired_connect_info()
for (; it != m_connections.end();) for (; it != m_connections.end();)
{ {
//EXLOGD("[core] check expired connect info: [%s] %d, %d %d %d\n", it->first.c_str(), it->second->ref_count, int(_now), int(it->second->ticket_start), int(_now - it->second->ticket_start)); //EXLOGD("[core] check expired connect info: [%s] %d, %d %d %d\n", it->first.c_str(), it->second->ref_count, int(_now), int(it->second->ticket_start), int(_now - it->second->ticket_start));
if (it->second->ref_count == 0 && _now - 15000 > it->second->ticket_start) if (it->second->ref_count == 0 && _now - TEMP_SESSION_ID_VALID_TIME > it->second->ticket_start)
{ {
EXLOGD("[core] remove connection info, because timeout: %s\n", it->first.c_str()); EXLOGD("[core] remove connection info, because timeout: %s\n", it->first.c_str());
delete it->second; delete it->second;
@ -100,7 +103,8 @@ bool TsSessionManager::free_connect_info(const ex_astr& sid)
it->second->ref_count--; it->second->ref_count--;
// 对于RDP来说此时不要移除连接信息系统自带RDP客户端在第一次连接时进行协议协商然后马上会断开之后立即重新连接一次第二次连接之前可能会提示证书信息如果用户长时间不操作可能会导致超时 // 对于RDP来说此时不要移除连接信息系统自带RDP客户端在第一次连接时进行协议协商然后马上会断开之后立即重新连接
// 一次(第二次连接之前可能会提示证书信息,如果用户长时间不操作,可能会导致超时)。
// 因此,我们将其引用计数减低,并更新一下最后访问时间,让定时器来移除它。 // 因此,我们将其引用计数减低,并更新一下最后访问时间,让定时器来移除它。
if (it->second->protocol_type != TP_PROTOCOL_TYPE_RDP) if (it->second->protocol_type != TP_PROTOCOL_TYPE_RDP)
{ {
@ -116,10 +120,10 @@ bool TsSessionManager::free_connect_info(const ex_astr& sid)
{ {
if (it->second->ref_count == 1) if (it->second->ref_count == 1)
it->second->ref_count = 0; it->second->ref_count = 0;
it->second->ticket_start = ex_get_tick_count() + 45000; // 我们将时间向后移动45秒这样如果没有发生RDP的第二次连接这个连接信息就会在一分钟后被清除。 // 我们将启动时间向后一段这样如果没有发生RDP的第二次连接这个连接信息过一会儿就会被清除。
it->second->ticket_start = ex_get_tick_count() + TEMP_SESSION_ID_VALID_TIME;
} }
return true; return true;
} }

View File

@ -60,7 +60,7 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
EXLOGE("[core] get conn info from web-server failed: can not connect to web-server.\n"); EXLOGE("[core] get conn info from web-server failed: can not connect to web-server.\n");
return TPE_NETWORK; return TPE_NETWORK;
} }
if (body.length() == 0) if (body.empty())
{ {
EXLOGE("[core] get conn info from web-server failed: got nothing.\n"); EXLOGE("[core] get conn info from web-server failed: got nothing.\n");
return TPE_NETWORK; return TPE_NETWORK;
@ -191,10 +191,10 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
// 注意account_id可以为-1表示这是一次测试连接。 // 注意account_id可以为-1表示这是一次测试连接。
// if (user_id <= 0 || host_id <= 0 // if (user_id <= 0 || host_id <= 0
// || // ||
if (user_username.length() == 0 if (user_username.empty()
|| host_ip.length() == 0 || conn_ip.length() == 0 || client_ip.length() == 0 || host_ip.empty() || conn_ip.empty() || client_ip.empty()
|| conn_port <= 0 || conn_port >= 65535 || conn_port <= 0 || conn_port >= 65535
|| acc_username.length() == 0 || acc_username.empty()
|| !(protocol_type == TP_PROTOCOL_TYPE_RDP || protocol_type == TP_PROTOCOL_TYPE_SSH || protocol_type == TP_PROTOCOL_TYPE_TELNET) || !(protocol_type == TP_PROTOCOL_TYPE_RDP || protocol_type == TP_PROTOCOL_TYPE_SSH || protocol_type == TP_PROTOCOL_TYPE_TELNET)
|| !(auth_type == TP_AUTH_TYPE_NONE || auth_type == TP_AUTH_TYPE_PASSWORD || auth_type == TP_AUTH_TYPE_PRIVATE_KEY) || !(auth_type == TP_AUTH_TYPE_NONE || auth_type == TP_AUTH_TYPE_PASSWORD || auth_type == TP_AUTH_TYPE_PRIVATE_KEY)
) )
@ -202,10 +202,14 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
return TPE_PARAM; return TPE_PARAM;
} }
if (auth_type != TP_AUTH_TYPE_NONE && acc_secret.length() == 0) // 认证方式为密码时,允许不设置密码,而是连接时由用户手动输入
{ if(acc_secret.empty() && !(auth_type == TP_AUTH_TYPE_NONE || auth_type == TP_AUTH_TYPE_PASSWORD))
return TPE_PARAM; return TPE_PARAM;
}
// if (auth_type != TP_AUTH_TYPE_NONE && acc_secret.length() == 0)
// {
// return TPE_PARAM;
// }
if (_enc && !acc_secret.empty()) if (_enc && !acc_secret.empty())
{ {

View File

@ -15,8 +15,8 @@ SshSession::SshSession(SshProxy* proxy, ssh_session rs_tp2cli, uint32_t dbg_id,
m_conn_info(nullptr), m_conn_info(nullptr),
m_conn_port(0), m_conn_port(0),
m_flags(0), m_flags(0),
m_auth_type(TP_AUTH_TYPE_NONE), m_auth_type(TP_AUTH_TYPE_NONE)
m_allow_user_input_password(false) // , m_allow_user_input_password(false)
{ {
ex_strformat(m_dbg_name, 128, "ssh-%d", dbg_id); ex_strformat(m_dbg_name, 128, "ssh-%d", dbg_id);
ex_strformat(m_dbg_client, 128, "%s:%d", client_ip, client_port); ex_strformat(m_dbg_client, 128, "%s:%d", client_ip, client_port);
@ -455,6 +455,7 @@ int SshSession::_on_auth_password_request(ssh_session /*session*/, const char* u
int SshSession::_do_auth(const char* user, const char* secret) int SshSession::_do_auth(const char* user, const char* secret)
{ {
EXLOGD("[%s] authenticating, user: %s\n", m_dbg_name.c_str(), user); EXLOGD("[%s] authenticating, user: %s\n", m_dbg_name.c_str(), user);
// EXLOGD("[%s] authenticating, user: %s, secret: %s\n", m_dbg_name.c_str(), user, secret);
// v3.6.0 // v3.6.0
// 场景 // 场景
@ -591,12 +592,12 @@ int SshSession::_do_auth(const char* user, const char* secret)
if (m_acc_secret.empty()) if (m_acc_secret.empty())
{ {
// 如果TP中未设置远程账号密码表示允许用户自行输入密码 // 如果TP中未设置远程账号密码表示允许用户自行输入密码
m_allow_user_input_password = true; // m_allow_user_input_password = true;
// 如果传入的password为特定值应该是由助手调用客户端填写的密码 // // 如果传入的password为特定值应该是由助手调用客户端填写的密码
// 直接返回认证失败,这样客户端会让用户输入密码 // // 直接返回认证失败,这样客户端会让用户输入密码
if (0 == strcmp(secret, "INTERACTIVE_USER")) // if (0 == strcmp(secret, "INTERACTIVE_USER"))
return SSH_AUTH_DENIED; // return SSH_AUTH_DENIED;
// 用户脱离TP-WEB直接使用客户端输入的密码 // 用户脱离TP-WEB直接使用客户端输入的密码
m_acc_secret = secret; m_acc_secret = secret;
@ -761,7 +762,7 @@ int SshSession::_do_auth(const char* user, const char* secret)
// about 'echo': // about 'echo':
// This is an optional variable. You can obtain a boolean if the user input should be echoed or // This is an optional variable. You can obtain a boolean if the user input should be echoed or
// hidden. For passwords it is usually hidden. // hidden. For password it is usually hidden.
EXLOGV("[%s] interactive login prompt(%s): %s\n", m_dbg_name.c_str(), echo ? "hidden" : "not hidden", prompt); EXLOGV("[%s] interactive login prompt(%s): %s\n", m_dbg_name.c_str(), echo ? "hidden" : "not hidden", prompt);
if (echo) if (echo)

View File

@ -151,7 +151,7 @@ private:
std::string m_acc_secret; std::string m_acc_secret;
uint32_t m_flags; uint32_t m_flags;
int m_auth_type; int m_auth_type;
bool m_allow_user_input_password; // bool m_allow_user_input_password;
bool m_first_auth; bool m_first_auth;
// 远程主机认证是否通过 // 远程主机认证是否通过

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,7 @@ $app.create_controls = function (cb_stack) {
//------------------------------- //-------------------------------
// 主机列表表格 // 主机列表表格
//------------------------------- //-------------------------------
var table_host_options = { let table_host_options = {
dom_id: 'table-host', dom_id: 'table-host',
data_source: { data_source: {
type: 'ajax-post', type: 'ajax-post',
@ -190,7 +190,7 @@ $app.create_controls = function (cb_stack) {
$app.dom.dlg_import_asset.modal({backdrop: 'static'}); $app.dom.dlg_import_asset.modal({backdrop: 'static'});
}); });
$app.dom.chkbox_host_select_all.click(function () { $app.dom.chkbox_host_select_all.click(function () {
var _objects = $('#' + $app.table_host.dom_id + ' tbody').find('[data-check-box]'); let _objects = $('#' + $app.table_host.dom_id + ' tbody').find('[data-check-box]');
if ($(this).is(':checked')) { if ($(this).is(':checked')) {
$.each(_objects, function (i, _obj) { $.each(_objects, function (i, _obj) {
$(_obj).prop('checked', true); $(_obj).prop('checked', true);
@ -227,8 +227,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
} else if (col_key === 'action') { } else if (col_key === 'action') {
// 绑定系统选择框事件 // 绑定系统选择框事件
cell_obj.find('[data-action]').click(function () { cell_obj.find('[data-action]').click(function () {
var host = $app.table_host.get_row(row_id); let host = $app.table_host.get_row(row_id);
var action = $(this).attr('data-action'); let action = $(this).attr('data-action');
if (action === 'edit') { if (action === 'edit') {
$app.dlg_edit_host.show_edit(row_id); $app.dlg_edit_host.show_edit(row_id);
} else if (action === 'account') { } else if (action === 'account') {
@ -265,12 +265,12 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
$app.on_table_host_render_created = function (render) { $app.on_table_host_render_created = function (render) {
render.filter_state = function (header, title, col) { render.filter_state = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">']; let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
_ret.push('<div class="tp-table-filter-inner">'); _ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>'); _ret.push('<div class="search-title">' + title + '</div>');
// 表格内嵌过滤器的DOM实体在这时生成 // 表格内嵌过滤器的DOM实体在这时生成
var filter_ctrl = header._table_ctrl.get_filter_ctrl('state'); let filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
_ret.push(filter_ctrl.render()); _ret.push(filter_ctrl.render());
_ret.push('</div></div>'); _ret.push('</div></div>');
@ -279,12 +279,12 @@ $app.on_table_host_render_created = function (render) {
}; };
render.filter_search = function (header, title, col) { render.filter_search = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-input">']; let _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
_ret.push('<div class="tp-table-filter-inner">'); _ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>'); _ret.push('<div class="search-title">' + title + '</div>');
// 表格内嵌过滤器的DOM实体在这时生成 // 表格内嵌过滤器的DOM实体在这时生成
var filter_ctrl = header._table_ctrl.get_filter_ctrl('search'); let filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
_ret.push(filter_ctrl.render()); _ret.push(filter_ctrl.render());
_ret.push('</div></div>'); _ret.push('</div></div>');
@ -297,7 +297,7 @@ $app.on_table_host_render_created = function (render) {
}; };
render.host_info = function (row_id, fields) { render.host_info = function (row_id, fields) {
var title, sub_title; let title, sub_title;
title = fields.name; title = fields.name;
sub_title = fields.ip; sub_title = fields.ip;
@ -306,7 +306,7 @@ $app.on_table_host_render_created = function (render) {
title = fields.ip; title = fields.ip;
} }
var desc = []; let desc = [];
if (fields.desc.length > 0) { if (fields.desc.length > 0) {
desc.push(fields.desc.replace(/\r/ig, "").replace(/\n/ig, "<br/>")); desc.push(fields.desc.replace(/\r/ig, "").replace(/\n/ig, "<br/>"));
} }
@ -314,7 +314,7 @@ $app.on_table_host_render_created = function (render) {
sub_title += ',由 ' + fields.router_ip + ':' + fields.router_port + ' 路由'; sub_title += ',由 ' + fields.router_ip + ':' + fields.router_port + ' 路由';
} }
var ret = []; let ret = [];
// ret.push('<div><span class="host-name" href="javascript:;">' + title + '</span>'); // ret.push('<div><span class="host-name" href="javascript:;">' + title + '</span>');
// if (desc.length > 0) { // if (desc.length > 0) {
// ret.push('<a class="host-id-desc" data-toggle="popover" data-placement="right"'); // ret.push('<a class="host-id-desc" data-toggle="popover" data-placement="right"');
@ -347,9 +347,9 @@ $app.on_table_host_render_created = function (render) {
}; };
render.host_state = function (row_id, fields) { render.host_state = function (row_id, fields) {
var _style, _state; let i, _style, _state;
for (var i = 0; i < $app.obj_states.length; ++i) { for (i = 0; i < $app.obj_states.length; ++i) {
if ($app.obj_states[i].id === fields.state) { if ($app.obj_states[i].id === fields.state) {
_style = $app.obj_states[i].style; _style = $app.obj_states[i].style;
_state = $app.obj_states[i].name; _state = $app.obj_states[i].name;
@ -365,7 +365,7 @@ $app.on_table_host_render_created = function (render) {
}; };
render.host_alive = function (row_id, fields) { render.host_alive = function (row_id, fields) {
var _style, _alive; let _style, _alive;
if (fields.alive === -1) { if (fields.alive === -1) {
_style = 'alive-unknown'; _style = 'alive-unknown';
@ -391,7 +391,7 @@ $app.on_table_host_render_created = function (render) {
_alive = '正在检测'; _alive = '正在检测';
} }
var ret = []; let ret = [];
ret.push('<div><a class="alive ' + _style + '" data-toggle="popover" data-placement="left"'); ret.push('<div><a class="alive ' + _style + '" data-toggle="popover" data-placement="left"');
ret.push(' data-html="true"'); ret.push(' data-html="true"');
@ -403,7 +403,7 @@ $app.on_table_host_render_created = function (render) {
}; };
render.make_host_action_btn = function (row_id, fields) { render.make_host_action_btn = function (row_id, fields) {
var h = []; let h = [];
h.push('<div class="btn-group btn-group-sm">'); h.push('<div class="btn-group btn-group-sm">');
h.push('<button type="button" class="btn btn-no-border dropdown-toggle" data-toggle="dropdown">'); h.push('<button type="button" class="btn btn-no-border dropdown-toggle" data-toggle="dropdown">');
h.push('<span data-selected-action>操作</span> <i class="fa fa-caret-right"></i></button>'); h.push('<span data-selected-action>操作</span> <i class="fa fa-caret-right"></i></button>');
@ -433,7 +433,7 @@ $app.on_table_host_header_created = function (header) {
}); });
// TODO: 当过滤器不是默认值时,让“重置过滤器按钮”有呼吸效果,避免用户混淆 - 实验性质 // TODO: 当过滤器不是默认值时,让“重置过滤器按钮”有呼吸效果,避免用户混淆 - 实验性质
// var t1 = function(){ // let t1 = function(){
// $app.dom.btn_table_host_reset_filter.fadeTo(1000, 1.0, function(){ // $app.dom.btn_table_host_reset_filter.fadeTo(1000, 1.0, function(){
// $app.dom.btn_table_host_reset_filter.fadeTo(1000, 0.2, t1); // $app.dom.btn_table_host_reset_filter.fadeTo(1000, 0.2, t1);
// }); // });
@ -447,8 +447,8 @@ $app.on_table_host_header_created = function (header) {
}; };
$app.check_host_all_selected = function (cb_stack) { $app.check_host_all_selected = function (cb_stack) {
var _all_checked = true; let _all_checked = true;
var _objs = $('#' + $app.table_host.dom_id + ' tbody').find('[data-check-box]'); let _objs = $('#' + $app.table_host.dom_id + ' tbody').find('[data-check-box]');
if (_objs.length === 0) { if (_objs.length === 0) {
_all_checked = false; _all_checked = false;
} else { } else {
@ -472,15 +472,15 @@ $app.check_host_all_selected = function (cb_stack) {
$app.on_btn_select_file_click = function () { $app.on_btn_select_file_click = function () {
var html = '<input id="file-selector" type="file" name="csvfile" accept=".csv,text/csv,text/comma-separated-values" class="hidden" value="" style="display: none;"/>'; let html = '<input id="file-selector" type="file" name="csvfile" accept=".csv,text/csv,text/comma-separated-values" class="hidden" value="" style="display: none;"/>';
$('body').after($(html)); $('body').after($(html));
var btn_file_selector = $("#file-selector"); let btn_file_selector = $("#file-selector");
btn_file_selector.change(function () { btn_file_selector.change(function () {
$app.dom.upload_file_message.hide(); $app.dom.upload_file_message.hide();
// var dom_file_name = $('#upload-file-name'); // let dom_file_name = $('#upload-file-name');
var file = null; let file = null;
if (btn_file_selector[0].files && btn_file_selector[0].files[0]) { if (btn_file_selector[0].files && btn_file_selector[0].files[0]) {
file = btn_file_selector[0].files[0]; file = btn_file_selector[0].files[0];
} else if (btn_file_selector[0].files && btn_file_selector[0].files.item(0)) { } else if (btn_file_selector[0].files && btn_file_selector[0].files.item(0)) {
@ -492,7 +492,7 @@ $app.on_btn_select_file_click = function () {
return; return;
} }
var _ext = file.name.substring(file.name.lastIndexOf('.')).toLocaleLowerCase(); let _ext = file.name.substring(file.name.lastIndexOf('.')).toLocaleLowerCase();
if (_ext !== '.csv') { if (_ext !== '.csv') {
$app.dom.upload_file_info.html('抱歉,仅支持导入 csv 格式的文件!'); $app.dom.upload_file_info.html('抱歉,仅支持导入 csv 格式的文件!');
return; return;
@ -503,7 +503,7 @@ $app.on_btn_select_file_click = function () {
return; return;
} }
var fileInfo = ''; let fileInfo = '';
fileInfo += file.name; fileInfo += file.name;
fileInfo += '<br/>'; fileInfo += '<br/>';
fileInfo += tp_size2str(file.size, 2); fileInfo += tp_size2str(file.size, 2);
@ -526,7 +526,7 @@ $app.on_btn_do_upload_click = function () {
.show(); .show();
var param = {}; let param = {};
$.ajaxFileUpload({ $.ajaxFileUpload({
url: "/asset/upload-import",// 需要链接到服务器地址 url: "/asset/upload-import",// 需要链接到服务器地址
fileElementId: "file-selector", // 文件选择框的id属性 fileElementId: "file-selector", // 文件选择框的id属性
@ -538,7 +538,7 @@ $app.on_btn_do_upload_click = function () {
console.log(data); console.log(data);
$('#file-selector').remove(); $('#file-selector').remove();
var ret = JSON.parse(data); let ret = JSON.parse(data);
console.log(ret); console.log(ret);
if (ret.code === TPE_OK) { if (ret.code === TPE_OK) {
@ -549,10 +549,10 @@ $app.on_btn_do_upload_click = function () {
$app.table_host.load_data(); $app.table_host.load_data();
} else { } else {
var err_msg = ['<i class="far fa-times-circle fa-fw"></i> 资产导入失败:' + ret.message]; let err_msg = ['<i class="far fa-times-circle fa-fw"></i> 资产导入失败:' + ret.message];
if (!_.isUndefined(ret.data)) { if (!_.isUndefined(ret.data)) {
err_msg.push('<div style="max-height:280px;overflow:auto;margin-left:20px;">'); err_msg.push('<div style="max-height:280px;overflow:auto;margin-left:20px;">');
var err_lines = []; let err_lines = [];
$.each(ret.data, function (i, item) { $.each(ret.data, function (i, item) {
err_lines.push('第' + item.line + '行:' + item.error); err_lines.push('第' + item.line + '行:' + item.error);
}); });
@ -580,11 +580,11 @@ $app.show_user_info = function (row_id) {
}; };
$app.get_selected_host = function (tbl) { $app.get_selected_host = function (tbl) {
var items = []; let items = [];
var _objs = $('#' + $app.table_host.dom_id + ' tbody tr td input[data-check-box]'); let _objs = $('#' + $app.table_host.dom_id + ' tbody tr td input[data-check-box]');
$.each(_objs, function (i, _obj) { $.each(_objs, function (i, _obj) {
if ($(_obj).is(':checked')) { if ($(_obj).is(':checked')) {
var _row_data = tbl.get_row(_obj); let _row_data = tbl.get_row(_obj);
// _all_checked = false; // _all_checked = false;
items.push(_row_data.id); items.push(_row_data.id);
} }
@ -609,7 +609,7 @@ $app._lock_hosts = function (host_ids) {
}; };
$app.on_btn_lock_host_click = function () { $app.on_btn_lock_host_click = function () {
var items = $app.get_selected_host($app.table_host); let items = $app.get_selected_host($app.table_host);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要禁用的主机!'); $tp.notify_error('请选择要禁用的主机!');
return; return;
@ -635,7 +635,7 @@ $app._unlock_hosts = function (host_ids) {
}; };
$app.on_btn_unlock_host_click = function () { $app.on_btn_unlock_host_click = function () {
var items = $app.get_selected_host($app.table_host); let items = $app.get_selected_host($app.table_host);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要解禁的主机!'); $tp.notify_error('请选择要解禁的主机!');
return; return;
@ -645,7 +645,7 @@ $app.on_btn_unlock_host_click = function () {
}; };
$app._remove_hosts = function (host_ids) { $app._remove_hosts = function (host_ids) {
var _fn_sure = function (cb_stack) { let _fn_sure = function (cb_stack) {
$tp.ajax_post_json('/asset/update-hosts', {action: 'remove', hosts: host_ids}, $tp.ajax_post_json('/asset/update-hosts', {action: 'remove', hosts: host_ids},
function (ret) { function (ret) {
if (ret.code === TPE_OK) { if (ret.code === TPE_OK) {
@ -665,7 +665,7 @@ $app._remove_hosts = function (host_ids) {
); );
}; };
var cb_stack = CALLBACK_STACK.create(); let cb_stack = CALLBACK_STACK.create();
$tp.dlg_confirm(cb_stack, { $tp.dlg_confirm(cb_stack, {
msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除主机将同时删除与之相关的账号,并将主机和账号从所在分组中移除,同时删除所有相关授权!</p></div><p>如果您希望临时禁止登录指定主机,可将其“禁用”!</p><p>您确定要移除选定的' + host_ids.length + '个主机吗?</p>', msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除主机将同时删除与之相关的账号,并将主机和账号从所在分组中移除,同时删除所有相关授权!</p></div><p>如果您希望临时禁止登录指定主机,可将其“禁用”!</p><p>您确定要移除选定的' + host_ids.length + '个主机吗?</p>',
fn_yes: _fn_sure fn_yes: _fn_sure
@ -673,7 +673,7 @@ $app._remove_hosts = function (host_ids) {
}; };
$app.on_btn_remove_host_click = function () { $app.on_btn_remove_host_click = function () {
var items = $app.get_selected_host($app.table_host); let items = $app.get_selected_host($app.table_host);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要删除的主机!'); $tp.notify_error('请选择要删除的主机!');
return; return;
@ -683,7 +683,7 @@ $app.on_btn_remove_host_click = function () {
}; };
$app.create_dlg_edit_host = function () { $app.create_dlg_edit_host = function () {
var dlg = {}; let dlg = {};
dlg.dom_id = 'dlg-edit-host'; dlg.dom_id = 'dlg-edit-host';
dlg.field_id = -1; // 主机id仅编辑模式 dlg.field_id = -1; // 主机id仅编辑模式
// dlg.field_type = -1; // dlg.field_type = -1;
@ -716,7 +716,7 @@ $app.create_dlg_edit_host = function () {
}; };
dlg.init = function (cb_stack) { dlg.init = function (cb_stack) {
var html = []; let html = [];
// // 创建类型选择框 // // 创建类型选择框
// html.push('<button type="button" class="btn btn-sm dropdown-toggle" data-toggle="dropdown">'); // html.push('<button type="button" class="btn btn-sm dropdown-toggle" data-toggle="dropdown">');
// html.push('<span data-selected-type>选择主机类型</span> <i class="fa fa-caret-right"></i></button>'); // html.push('<span data-selected-type>选择主机类型</span> <i class="fa fa-caret-right"></i></button>');
@ -730,10 +730,10 @@ $app.create_dlg_edit_host = function () {
// //
// // 绑定类型选择框事件 // // 绑定类型选择框事件
// $('#' + dlg.dom_id + ' li a[data-type-selector]').click(function () { // $('#' + dlg.dom_id + ' li a[data-type-selector]').click(function () {
// var select = parseInt($(this).attr('data-type-selector')); // let select = parseInt($(this).attr('data-type-selector'));
// if (dlg.field_type === select) // if (dlg.field_type === select)
// return; // return;
// var name = $app.id2name($app.host_types, select); // let name = $app.id2name($app.host_types, select);
// if (_.isUndefined(name)) { // if (_.isUndefined(name)) {
// name = '选择主机类型角色'; // name = '选择主机类型角色';
// dlg.field_type = -1; // dlg.field_type = -1;
@ -772,9 +772,9 @@ $app.create_dlg_edit_host = function () {
}; };
dlg.init_fields = function (host) { dlg.init_fields = function (host) {
// var type_name = '选择主机类型'; // let type_name = '选择主机类型';
// dlg.field_type = -1; // dlg.field_type = -1;
// var os_name = '选择操作系统'; // let os_name = '选择操作系统';
dlg.field_id = -1; dlg.field_id = -1;
dlg.field_os_type = -1; dlg.field_os_type = -1;
@ -792,7 +792,7 @@ $app.create_dlg_edit_host = function () {
dlg.field_id = host.id; dlg.field_id = host.id;
dlg.dom.dlg_title.html('编辑主机:'); dlg.dom.dlg_title.html('编辑主机:');
var _name = $app.id2name($app.host_os_type, host.os_type); let _name = $app.id2name($app.host_os_type, host.os_type);
if (!_.isUndefined(_name)) { if (!_.isUndefined(_name)) {
// os_name = _name; // os_name = _name;
} }
@ -831,7 +831,7 @@ $app.create_dlg_edit_host = function () {
}; };
dlg.show_edit = function (row_id) { dlg.show_edit = function (row_id) {
var host = $app.table_host.get_row(row_id); let host = $app.table_host.get_row(row_id);
dlg.init_fields(host); dlg.init_fields(host);
dlg.dom.dialog.modal({backdrop: 'static'}); dlg.dom.dialog.modal({backdrop: 'static'});
}; };
@ -909,14 +909,14 @@ $app.create_dlg_edit_host = function () {
if (!dlg.check_input()) if (!dlg.check_input())
return; return;
var action = (dlg.field_id === -1) ? '添加' : '更新'; let action = (dlg.field_id === -1) ? '添加' : '更新';
// var router_addr = ''; // let router_addr = '';
// if (dlg.field_conn_mode === 1) { // if (dlg.field_conn_mode === 1) {
// router_addr = dlg.field_router_ip + ':' + dlg.field_router_port; // router_addr = dlg.field_router_ip + ':' + dlg.field_router_port;
// } // }
var args = { let args = {
id: dlg.field_id, id: dlg.field_id,
os_type: dlg.field_os_type, os_type: dlg.field_os_type,
ip: dlg.field_ip, ip: dlg.field_ip,
@ -948,7 +948,7 @@ $app.create_dlg_edit_host = function () {
}; };
$app.create_dlg_accounts = function () { $app.create_dlg_accounts = function () {
var dlg = {}; let dlg = {};
dlg.dom_id = 'dlg-accounts'; dlg.dom_id = 'dlg-accounts';
dlg.host_row_id = -1; dlg.host_row_id = -1;
dlg.host = null; dlg.host = null;
@ -977,7 +977,7 @@ $app.create_dlg_accounts = function () {
// 账号列表表格 // 账号列表表格
//------------------------------- //-------------------------------
var table_acc_options = { let table_acc_options = {
dom_id: 'table-acc', dom_id: 'table-acc',
data_source: { data_source: {
type: 'none' type: 'none'
@ -1069,7 +1069,7 @@ $app.create_dlg_accounts = function () {
}); });
dlg.dom.chkbox_acc_select_all.click(function () { dlg.dom.chkbox_acc_select_all.click(function () {
var _objects = $('#' + $app.table_acc.dom_id + ' tbody').find('[data-check-box]'); let _objects = $('#' + $app.table_acc.dom_id + ' tbody').find('[data-check-box]');
if ($(this).is(':checked')) { if ($(this).is(':checked')) {
$.each(_objects, function (i, _obj) { $.each(_objects, function (i, _obj) {
$(_obj).prop('checked', true); $(_obj).prop('checked', true);
@ -1085,11 +1085,11 @@ $app.create_dlg_accounts = function () {
}; };
dlg.get_selected_acc = function (tbl) { dlg.get_selected_acc = function (tbl) {
var items = []; let items = [];
var _objs = $('#' + tbl.dom_id + ' tbody tr td input[data-check-box]'); let _objs = $('#' + tbl.dom_id + ' tbody tr td input[data-check-box]');
$.each(_objs, function (i, _obj) { $.each(_objs, function (i, _obj) {
if ($(_obj).is(':checked')) { if ($(_obj).is(':checked')) {
var _row_data = tbl.get_row(_obj); let _row_data = tbl.get_row(_obj);
items.push(_row_data.id); items.push(_row_data.id);
} }
}); });
@ -1116,7 +1116,7 @@ $app.create_dlg_accounts = function () {
}; };
dlg.on_btn_lock_acc_click = function () { dlg.on_btn_lock_acc_click = function () {
var items = dlg.get_selected_acc($app.table_acc); let items = dlg.get_selected_acc($app.table_acc);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要禁用的账号!'); $tp.notify_error('请选择要禁用的账号!');
return; return;
@ -1146,7 +1146,7 @@ $app.create_dlg_accounts = function () {
}; };
dlg.on_btn_unlock_acc_click = function () { dlg.on_btn_unlock_acc_click = function () {
var items = dlg.get_selected_acc($app.table_acc); let items = dlg.get_selected_acc($app.table_acc);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要解禁的账号!'); $tp.notify_error('请选择要解禁的账号!');
return; return;
@ -1156,7 +1156,7 @@ $app.create_dlg_accounts = function () {
}; };
dlg._remove_acc = function (acc_ids) { dlg._remove_acc = function (acc_ids) {
var _fn_sure = function (cb_stack) { let _fn_sure = function (cb_stack) {
$tp.ajax_post_json('/asset/update-accounts', {action: 'remove', host_id: dlg.host.id, accounts: acc_ids}, $tp.ajax_post_json('/asset/update-accounts', {action: 'remove', host_id: dlg.host.id, accounts: acc_ids},
function (ret) { function (ret) {
if (ret.code === TPE_OK) { if (ret.code === TPE_OK) {
@ -1166,7 +1166,7 @@ $app.create_dlg_accounts = function () {
.exec(); .exec();
$tp.notify_success('删除主机操作成功!'); $tp.notify_success('删除主机操作成功!');
var update_args = { let update_args = {
acc_count: dlg.host.acc_count - acc_ids.length acc_count: dlg.host.acc_count - acc_ids.length
}; };
$app.table_host.update_row(dlg.host_row_id, update_args); $app.table_host.update_row(dlg.host_row_id, update_args);
@ -1184,7 +1184,7 @@ $app.create_dlg_accounts = function () {
); );
}; };
var cb_stack = CALLBACK_STACK.create(); let cb_stack = CALLBACK_STACK.create();
$tp.dlg_confirm(cb_stack, { $tp.dlg_confirm(cb_stack, {
msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p></div><p>如果您希望临时禁止以指定账号登录远程主机,可将其“禁用”!</p><p>您确定要移除选定的' + acc_ids.length + '个账号吗?</p>', msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p></div><p>如果您希望临时禁止以指定账号登录远程主机,可将其“禁用”!</p><p>您确定要移除选定的' + acc_ids.length + '个账号吗?</p>',
fn_yes: _fn_sure fn_yes: _fn_sure
@ -1192,7 +1192,7 @@ $app.create_dlg_accounts = function () {
}; };
dlg.on_btn_remove_acc_click = function () { dlg.on_btn_remove_acc_click = function () {
var items = dlg.get_selected_acc($app.table_acc); let items = dlg.get_selected_acc($app.table_acc);
if (items.length === 0) { if (items.length === 0) {
$tp.notify_error('请选择要删除的账号!'); $tp.notify_error('请选择要删除的账号!');
return; return;
@ -1241,9 +1241,9 @@ $app.create_dlg_accounts = function () {
// 绑定系统选择框事件 // 绑定系统选择框事件
cell_obj.find('[data-action]').click(function () { cell_obj.find('[data-action]').click(function () {
var action = $(this).attr('data-action'); let action = $(this).attr('data-action');
var acc_id = $(this).attr('data-id'); let acc_id = $(this).attr('data-id');
var acc = tbl.get_row(row_id); let acc = tbl.get_row(row_id);
if (action === 'edit') { if (action === 'edit') {
$app.dlg_edit_account.show_edit(dlg.host_row_id, acc); $app.dlg_edit_account.show_edit(dlg.host_row_id, acc);
@ -1261,12 +1261,12 @@ $app.create_dlg_accounts = function () {
dlg.on_table_acc_render_created = function (render) { dlg.on_table_acc_render_created = function (render) {
// render.filter_state = function (header, title, col) { // render.filter_state = function (header, title, col) {
// var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">']; // let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
// _ret.push('<div class="tp-table-filter-inner">'); // _ret.push('<div class="tp-table-filter-inner">');
// _ret.push('<div class="search-title">' + title + '</div>'); // _ret.push('<div class="search-title">' + title + '</div>');
// //
// // 表格内嵌过滤器的DOM实体在这时生成 // // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('state'); // let filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
// _ret.push(filter_ctrl.render()); // _ret.push(filter_ctrl.render());
// //
// _ret.push('</div></div>'); // _ret.push('</div></div>');
@ -1275,12 +1275,12 @@ $app.create_dlg_accounts = function () {
// }; // };
// //
// render.filter_search = function (header, title, col) { // render.filter_search = function (header, title, col) {
// var _ret = ['<div class="tp-table-filter tp-table-filter-input">']; // let _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
// _ret.push('<div class="tp-table-filter-inner">'); // _ret.push('<div class="tp-table-filter-inner">');
// _ret.push('<div class="search-title">' + title + '</div>'); // _ret.push('<div class="search-title">' + title + '</div>');
// //
// // 表格内嵌过滤器的DOM实体在这时生成 // // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('search'); // let filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
// _ret.push(filter_ctrl.render()); // _ret.push(filter_ctrl.render());
// //
// _ret.push('</div></div>'); // _ret.push('</div></div>');
@ -1294,7 +1294,7 @@ $app.create_dlg_accounts = function () {
render.acc_info = function (row_id, fields) { render.acc_info = function (row_id, fields) {
return fields.username; return fields.username;
// var ret = []; // let ret = [];
// //
// ret.push('<span class="user-surname">' + fields.username + '@' + fields.host_ip + '</span>'); // ret.push('<span class="user-surname">' + fields.username + '@' + fields.host_ip + '</span>');
// if (fields.router_ip.length > 0) // if (fields.router_ip.length > 0)
@ -1330,9 +1330,9 @@ $app.create_dlg_accounts = function () {
}; };
render.acc_state = function (row_id, fields) { render.acc_state = function (row_id, fields) {
var _style, _state; let i, _style, _state;
for (var i = 0; i < $app.obj_states.length; ++i) { for (i = 0; i < $app.obj_states.length; ++i) {
if ($app.obj_states[i].id === fields.state) { if ($app.obj_states[i].id === fields.state) {
_style = $app.obj_states[i].style; _style = $app.obj_states[i].style;
_state = $app.obj_states[i].name; _state = $app.obj_states[i].name;
@ -1348,7 +1348,7 @@ $app.create_dlg_accounts = function () {
}; };
render.make_host_action_btn = function (row_id, fields) { render.make_host_action_btn = function (row_id, fields) {
// var h = []; // let h = [];
// h.push('<div class="btn-group btn-group-sm">'); // h.push('<div class="btn-group btn-group-sm">');
// h.push('<button type="button" class="btn btn-no-border dropdown-toggle" data-toggle="dropdown">'); // h.push('<button type="button" class="btn btn-no-border dropdown-toggle" data-toggle="dropdown">');
// h.push('<span data-selected-action>操作</span> <i class="fa fa-caret-right"></i></button>'); // h.push('<span data-selected-action>操作</span> <i class="fa fa-caret-right"></i></button>');
@ -1367,7 +1367,7 @@ $app.create_dlg_accounts = function () {
// return h.join(''); // return h.join('');
var ret = []; let ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">'); ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<btn class="btn btn-primary" data-action="edit" data-id="' + fields.id + '"><i class="fa fa-edit"></i> 编辑</btn>'); ret.push('<btn class="btn btn-primary" data-action="edit" data-id="' + fields.id + '"><i class="fa fa-edit"></i> 编辑</btn>');
@ -1398,8 +1398,8 @@ $app.create_dlg_accounts = function () {
}; };
dlg.check_acc_all_selected = function (cb_stack) { dlg.check_acc_all_selected = function (cb_stack) {
var _all_checked = true; let _all_checked = true;
var _objs = $('#' + $app.table_acc.dom_id + ' tbody').find('[data-check-box]'); let _objs = $('#' + $app.table_acc.dom_id + ' tbody').find('[data-check-box]');
if (_objs.length === 0) { if (_objs.length === 0) {
_all_checked = false; _all_checked = false;
} else { } else {
@ -1426,7 +1426,7 @@ $app.create_dlg_accounts = function () {
}; };
$app.create_dlg_edit_account = function () { $app.create_dlg_edit_account = function () {
var dlg = {}; let dlg = {};
dlg.dom_id = 'dlg-edit-account'; dlg.dom_id = 'dlg-edit-account';
dlg.host_row_id = -1; dlg.host_row_id = -1;
dlg.host = null; dlg.host = null;
@ -1460,6 +1460,8 @@ $app.create_dlg_edit_account = function () {
prompt_password: $('#account-password-prompt'), prompt_password: $('#account-password-prompt'),
btn_show_password: $('#btn-show-account-password'), btn_show_password: $('#btn-show-account-password'),
btn_show_password_icon: $('#btn-show-account-password i'), btn_show_password_icon: $('#btn-show-account-password i'),
btn_clear_password: $('#btn-clear-password'),
block_clear_password: $('#block-clear-password'),
btn_test: $('#btn-edit-account-test'), btn_test: $('#btn-edit-account-test'),
btn_save: $('#btn-edit-account-save') btn_save: $('#btn-edit-account-save')
}; };
@ -1481,6 +1483,24 @@ $app.create_dlg_edit_account = function () {
} }
}); });
dlg.dom.btn_clear_password.click(function () {
$tp.ajax_post_json('/asset/clear-account-password', {
host_id: dlg.host.id,
acc_id: dlg.field_id
},
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('远程账号预设密码清除成功!');
} else {
$tp.notify_error('远程账号预设密码清除失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,远程账号预设密码清除失败!');
}
);
});
cb_stack.exec(); cb_stack.exec();
}; };
@ -1492,6 +1512,7 @@ $app.create_dlg_edit_account = function () {
dlg.account = null; dlg.account = null;
dlg.field_id = -1; dlg.field_id = -1;
dlg.dom.dlg_title.html('添加远程账号'); dlg.dom.dlg_title.html('添加远程账号');
dlg.dom.block_clear_password.hide();
if (dlg.host.os_type === TP_OS_TYPE_LINUX) { if (dlg.host.os_type === TP_OS_TYPE_LINUX) {
dlg.dom.protocol_type.val(TP_PROTOCOL_TYPE_SSH); dlg.dom.protocol_type.val(TP_PROTOCOL_TYPE_SSH);
@ -1506,6 +1527,7 @@ $app.create_dlg_edit_account = function () {
dlg.account = account; dlg.account = account;
dlg.field_id = account.id; dlg.field_id = account.id;
dlg.dom.dlg_title.html('编辑:' + account.username); dlg.dom.dlg_title.html('编辑:' + account.username);
dlg.dom.block_clear_password.show();
dlg.dom.username.val(account.username); dlg.dom.username.val(account.username);
@ -1525,7 +1547,7 @@ $app.create_dlg_edit_account = function () {
dlg.on_protocol_change = function () { dlg.on_protocol_change = function () {
dlg.field_protocol = parseInt(dlg.dom.protocol_type.val()); dlg.field_protocol = parseInt(dlg.dom.protocol_type.val());
var html = []; let html = [];
if (dlg.field_protocol === TP_PROTOCOL_TYPE_RDP) { if (dlg.field_protocol === TP_PROTOCOL_TYPE_RDP) {
dlg.dom.block_rdp_param.show(); dlg.dom.block_rdp_param.show();
dlg.dom.block_ssh_param.hide(); dlg.dom.block_ssh_param.hide();
@ -1673,11 +1695,12 @@ $app.create_dlg_edit_account = function () {
} }
if (dlg.field_auth_type === TP_AUTH_TYPE_PASSWORD) { if (dlg.field_auth_type === TP_AUTH_TYPE_PASSWORD) {
if (dlg.field_id === -1 && dlg.field_password.length === 0) { // 可以不用设置密码,在远程登录时用户再手动填写。
dlg.dom.password.focus(); // if (dlg.field_id === -1 && dlg.field_password.length === 0) {
$tp.notify_error('请填写登录远程主机的密码!'); // dlg.dom.password.focus();
return false; // $tp.notify_error('请填写登录远程主机的密码!');
} // return false;
// }
dlg.field_pri_key = ''; dlg.field_pri_key = '';
} else if (dlg.field_auth_type === TP_AUTH_TYPE_PRIVATE_KEY) { } else if (dlg.field_auth_type === TP_AUTH_TYPE_PRIVATE_KEY) {
if (dlg.field_id === -1 && dlg.field_pri_key.length === 0) { if (dlg.field_id === -1 && dlg.field_pri_key.length === 0) {
@ -1700,7 +1723,7 @@ $app.create_dlg_edit_account = function () {
if (!dlg.check_input()) if (!dlg.check_input())
return; return;
var action = (dlg.field_id === -1) ? '添加' : '更新'; let action = (dlg.field_id === -1) ? '添加' : '更新';
// 如果id为-1表示创建否则表示更新 // 如果id为-1表示创建否则表示更新
$tp.ajax_post_json('/asset/update-account', { $tp.ajax_post_json('/asset/update-account', {
@ -1726,7 +1749,7 @@ $app.create_dlg_edit_account = function () {
if (dlg.field_id === -1) { if (dlg.field_id === -1) {
// 新建账号成功了,更新界面上对应主机的账号数 // 新建账号成功了,更新界面上对应主机的账号数
var update_args = { let update_args = {
acc_count: dlg.host.acc_count + 1 acc_count: dlg.host.acc_count + 1
}; };
$app.table_host.update_row(dlg.host_row_id, update_args); $app.table_host.update_row(dlg.host_row_id, update_args);
@ -1750,6 +1773,8 @@ $app.create_dlg_edit_account = function () {
if (!dlg.check_input()) if (!dlg.check_input())
return; return;
let is_interactive = (dlg.field_password.length === 0);
$assist.do_teleport( $assist.do_teleport(
{ {
mode: 0, mode: 0,
@ -1764,7 +1789,8 @@ $app.create_dlg_edit_account = function () {
password: dlg.field_password, password: dlg.field_password,
pri_key: dlg.field_pri_key, pri_key: dlg.field_pri_key,
username_prompt: dlg.field_prompt_username, username_prompt: dlg.field_prompt_username,
password_prompt: dlg.field_prompt_password password_prompt: dlg.field_prompt_password,
is_interactive: is_interactive
}, },
function () { function () {
// func_success // func_success

View File

@ -4,12 +4,10 @@ $app.on_init = function (cb_stack) {
$app.dom = { $app.dom = {
btn_sel_group: $('#btn-sel-group button') btn_sel_group: $('#btn-sel-group button')
, btn_refresh_host: $('#btn-refresh-host') , btn_refresh_host: $('#btn-refresh-host')
// , group_list_for_sel: $('#btn-sel-group ul')
// , group_selected: $('#group-selected')
}; };
// console.log($app.options); // console.log($app.options);
if(!$app.options.core_cfg.detected) { if (!$app.options.core_cfg.detected) {
$tp.notify_error('核心服务未启动,无法进行远程连接!'); $tp.notify_error('核心服务未启动,无法进行远程连接!');
cb_stack.exec(); cb_stack.exec();
return; return;
@ -27,17 +25,10 @@ $app.on_init = function (cb_stack) {
//=================================== //===================================
$app.create_controls = function (cb_stack) { $app.create_controls = function (cb_stack) {
// var html = [];
// $.each($app.options.host_groups, function (i, item) {
// html.push('<li><a href="javascript:;" data-tp-selector="' + item.id + '" data-name="' + item.name + '"><i class="fa fa-caret-right fa-fw"></i> ' + item.name + '</a></li>');
// });
// $app.dom.group_list_for_sel.append($(html.join('')));
//
//------------------------------- //-------------------------------
// 资产列表表格 // 资产列表表格
//------------------------------- //-------------------------------
var table_host_options = { let table_host_options = {
dom_id: 'table-host', dom_id: 'table-host',
data_source: { data_source: {
type: 'ajax-post', type: 'ajax-post',
@ -130,13 +121,14 @@ $app.create_controls = function (cb_stack) {
$app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) { $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
if (col_key === 'action') { if (col_key === 'action') {
// 绑定系统选择框事件 // 绑定系统选择框事件
cell_obj.find('[data-action]').click(function (e) { cell_obj.find('[data-action]').click(function (e) {
var action = $(this).attr('data-action'); let action = $(this).attr('data-action');
var protocol_sub_type = $(this).attr('data-sub-protocol'); let protocol_sub_type = $(this).attr('data-sub-protocol');
var uni_id = $(this).attr('data-id'); let uni_id = $(this).attr('data-id');
var acc_id = parseInt($(this).attr('data-acc-id')); let acc_id = parseInt($(this).attr('data-acc-id'));
var host_id = parseInt($(this).attr('data-host-id')); let host_id = parseInt($(this).attr('data-host-id'));
if (action === 'rdp') { if (action === 'rdp') {
$app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_RDP, TP_PROTOCOL_TYPE_RDP_DESKTOP); $app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_RDP, TP_PROTOCOL_TYPE_RDP_DESKTOP);
@ -146,6 +138,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
$app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_SSH, protocol_sub_type); $app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_SSH, protocol_sub_type);
} else if (action === 'telnet') { } else if (action === 'telnet') {
$app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_TELNET, TP_PROTOCOL_TYPE_TELNET_SHELL); $app.connect_remote(uni_id, acc_id, host_id, TP_PROTOCOL_TYPE_TELNET, TP_PROTOCOL_TYPE_TELNET_SHELL);
} else if (action === 'get_config') {
$app.get_remote_connection_config(acc_id, host_id);
} }
}); });
} }
@ -154,12 +148,12 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
$app.on_table_host_render_created = function (render) { $app.on_table_host_render_created = function (render) {
render.filter_state = function (header, title, col) { render.filter_state = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">']; let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
_ret.push('<div class="tp-table-filter-inner">'); _ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>'); _ret.push('<div class="search-title">' + title + '</div>');
// 表格内嵌过滤器的DOM实体在这时生成 // 表格内嵌过滤器的DOM实体在这时生成
var filter_ctrl = header._table_ctrl.get_filter_ctrl('state'); let filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
_ret.push(filter_ctrl.render()); _ret.push(filter_ctrl.render());
_ret.push('</div></div>'); _ret.push('</div></div>');
@ -168,12 +162,12 @@ $app.on_table_host_render_created = function (render) {
}; };
render.filter_search = function (header, title, col) { render.filter_search = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-input">']; let _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
_ret.push('<div class="tp-table-filter-inner">'); _ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>'); _ret.push('<div class="search-title">' + title + '</div>');
// 表格内嵌过滤器的DOM实体在这时生成 // 表格内嵌过滤器的DOM实体在这时生成
var filter_ctrl = header._table_ctrl.get_filter_ctrl('search'); let filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
_ret.push(filter_ctrl.render()); _ret.push(filter_ctrl.render());
_ret.push('</div></div>'); _ret.push('</div></div>');
@ -182,7 +176,7 @@ $app.on_table_host_render_created = function (render) {
}; };
render.host_info = function (row_id, fields) { render.host_info = function (row_id, fields) {
var title, sub_title; let title, sub_title;
title = fields.h_name; title = fields.h_name;
sub_title = fields.ip; sub_title = fields.ip;
@ -193,77 +187,112 @@ $app.on_table_host_render_created = function (render) {
// title = fields.a_name + '@' + title; // title = fields.a_name + '@' + title;
var desc = []; // let desc = [];
if (fields.router_ip.length > 0) { if (fields.router_ip.length > 0) {
sub_title += ',由 ' + fields.router_ip + ':' + fields.router_port + ' 路由'; sub_title += ',由 ' + fields.router_ip + ':' + fields.router_port + ' 路由';
} }
var ret = []; let ret = [];
if (desc.length > 0) { // if (desc.length > 0) {
ret.push('<div><a class="host-name host-name-desc" data-toggle="popover" data-placement="right"'); // ret.push('<div><a class="host-name host-name-desc" data-toggle="popover" data-placement="right"');
ret.push(' data-html="true"'); // ret.push(' data-html="true"');
ret.push(' data-content="' + desc.join('') + '"'); // ret.push(' data-content="' + desc.join('') + '"');
ret.push('>' + title + '</a>'); // ret.push('>' + title + '</a>');
} else { // } else {
ret.push('<div><span class="host-name">' + title + '</span>'); // ret.push('<div><span class="host-name">' + title + '</span>');
} // }
ret.push('<div><span class="host-name">' + title + '</span>');
ret.push('</div><div class="host-ip" href="javascript:;" data-host-desc="' + sub_title + '">' + sub_title + '</div>'); ret.push('</div><div class="host-ip" href="javascript:;" data-host-desc="' + sub_title + '">' + sub_title + '</div>');
return ret.join(''); return ret.join('');
}; };
render.account = function (row_id, fields) { render.account = function (row_id, fields) {
var h = []; let h = [];
for (var i = 0; i < fields.accs.length; ++i) {
var acc = fields.accs[i]; // console.log('acc', fields);
h.push('<div class="remote-info-group" id =' + "account-id-" + acc.id + '"><ul>'); if (fields.h_state !== TP_STATE_NORMAL || (fields.gh_state !== TP_STATE_NORMAL && fields.gh_state !== 0)) {
// 1. 主机已经被禁用,不显示相关账号。
// 2. 主机所在分组已经被禁用,不显示相关账号。
return;
}
for (let i = 0; i < fields.accs.length; ++i) {
let acc = fields.accs[i];
h.push('<div class="remote-info-group"><ul>');
h.push('<li>' + acc.a_name + '</li>'); h.push('<li>' + acc.a_name + '</li>');
h.push('</ul></div>'); h.push('</ul></div>');
} }
return h.join(''); return h.join('');
}; };
render.action = function (row_id, fields) { render.action = function (row_id, fields) {
// console.log(fields); // console.log('action', fields);
var h = [];
for (var i = 0; i < fields.accs.length; ++i) { let is_disabled = false;
var acc = fields.accs[i]; let disable_msg = '';
var act_btn = [];
if (fields.h_state !== TP_STATE_NORMAL) {
is_disabled = true;
disable_msg = '无可用远程连接,主机已被禁用';
}
if (fields.gh_state !== TP_STATE_NORMAL && fields.gh_state !== 0) {
is_disabled = true;
disable_msg = '无可用远程连接,主机所在分组已被禁用';
}
if (is_disabled) {
let h = [];
h.push('<div><div class="remote-action-group"><div class="btn-group btn-group-sm">');
h.push('<button type="button" class="btn btn-disabled" disabled><i class="fa fa-ban fa-fw"></i> ');
h.push(disable_msg);
h.push('</button></div></div>');
return h.join('');
}
let h = [];
for (let i = 0; i < fields.accs.length; ++i) {
let acc = fields.accs[i];
let act_btn = [];
is_disabled = false;
disable_msg = '';
var disabled = '';
if (acc.a_state !== TP_STATE_NORMAL) if (acc.a_state !== TP_STATE_NORMAL)
disabled = '账号已禁用'; disable_msg = '账号已被禁用';
if (disabled.length === 0 && (acc.policy_auth_type === TP_POLICY_AUTH_USER_gACC || acc.policy_auth_type === TP_POLICY_AUTH_gUSER_gACC) && acc.ga_state !== TP_STATE_NORMAL) if (disable_msg.length === 0 && (acc.policy_auth_type === TP_POLICY_AUTH_USER_gACC || acc.policy_auth_type === TP_POLICY_AUTH_gUSER_gACC) && acc.ga_state !== TP_STATE_NORMAL)
disabled = '账号所在组已禁用'; disable_msg = '账号所在分组已被禁用';
if (disabled.length === 0 && fields.h_state !== TP_STATE_NORMAL) // if (disable_msg.length === 0 && fields.h_state !== TP_STATE_NORMAL)
disabled = '主机已禁用'; // disable_msg = '主机已被禁用';
if (disabled.length === 0 && (acc.policy_auth_type === TP_POLICY_AUTH_USER_gHOST || acc.policy_auth_type === TP_POLICY_AUTH_gUSER_gHOST) && fields.gh_state !== TP_STATE_NORMAL) // if (disable_msg.length === 0 && (acc.policy_auth_type === TP_POLICY_AUTH_USER_gHOST || acc.policy_auth_type === TP_POLICY_AUTH_gUSER_gHOST) && fields.gh_state !== TP_STATE_NORMAL)
disabled = '主机所在组已禁用'; // disable_msg = '主机所在组已被禁用';
if (disabled.length > 0) { if (disable_msg.length > 0)
act_btn.push('<li class="remote-action-state state-disabled">'); is_disabled = true;
act_btn.push('<i class="fa fa-ban fa-fw"></i> ' + disabled);
act_btn.push('</li>'); if (acc.protocol_type === TP_PROTOCOL_TYPE_RDP) {
} else { if (!is_disabled) {
if (acc.protocol_type === TP_PROTOCOL_TYPE_RDP) {
if (!$app.options.core_cfg.rdp.enable) { if (!$app.options.core_cfg.rdp.enable) {
act_btn.push('<li class="remote-action-state state-disabled">'); is_disabled = true;
act_btn.push('<i class="fa fa-ban fa-fw"></i> RDP协议未启用'); disable_msg = 'RDP协议未启用';
act_btn.push('</li>');
} else { } else {
if ((acc.policy_.flag_rdp & TP_FLAG_RDP_DESKTOP) !== 0) { if ((acc.policy_.flag_rdp & TP_FLAG_RDP_DESKTOP) !== 0) {
act_btn.push('<div class="btn-group btn-group-sm">'); act_btn.push('<div class="btn-group btn-group-sm">');
act_btn.push('<button type="button" class="btn btn-primary" data-action="rdp" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_RDP_DESKTOP + '"><i class="fa fa-desktop fa-fw"></i> RDP</button>'); act_btn.push('<button type="button" class="btn btn-primary" data-action="rdp" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_RDP_DESKTOP + '"><i class="fa fa-desktop fa-fw"></i> RDP</button>');
act_btn.push('<a href="javascript:;" class="btn btn-primary dropdown-toggle" data-action="rdp-option" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_RDP_DESKTOP + '">'); act_btn.push('<button type="button" class="btn btn-primary dropdown-toggle" data-action="rdp-option" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_RDP_DESKTOP + '">');
act_btn.push('<i class="fa fa-cog"></i>'); act_btn.push('<i class="fa fa-cog"></i>');
act_btn.push('</a>'); act_btn.push('</button>');
act_btn.push('</div>'); act_btn.push('</div>');
} }
} }
} else if (acc.protocol_type === TP_PROTOCOL_TYPE_SSH) { } else {
disable_msg = 'RPD' + disable_msg;
}
} else if (acc.protocol_type === TP_PROTOCOL_TYPE_SSH) {
if (!is_disabled) {
if (!$app.options.core_cfg.ssh.enable) { if (!$app.options.core_cfg.ssh.enable) {
act_btn.push('<li class="remote-action-state state-disabled">'); is_disabled = true;
act_btn.push('<i class="fa fa-ban fa-fw"></i> SSH协议未启用'); disable_msg = 'SSH协议未启用';
act_btn.push('</li>');
} else { } else {
act_btn.push('<div class="btn-group btn-group-sm">'); act_btn.push('<div class="btn-group btn-group-sm">');
if ((acc.policy_.flag_ssh & TP_FLAG_SSH_SHELL) !== 0) { if ((acc.policy_.flag_ssh & TP_FLAG_SSH_SHELL) !== 0) {
@ -275,23 +304,49 @@ $app.on_table_host_render_created = function (render) {
} }
act_btn.push('</div>'); act_btn.push('</div>');
} }
} else if (acc.protocol_type === TP_PROTOCOL_TYPE_TELNET) { } else {
disable_msg = 'SSH' + disable_msg;
}
} else if (acc.protocol_type === TP_PROTOCOL_TYPE_TELNET) {
if (!is_disabled) {
if (!$app.options.core_cfg.telnet.enable) { if (!$app.options.core_cfg.telnet.enable) {
act_btn.push('<li class="remote-action-state state-disabled">'); is_disabled = true;
act_btn.push('<i class="fa fa-ban fa-fw"></i> TELNET协议未启用'); disable_msg = 'TELNET协议未启用';
act_btn.push('</li>');
} else { } else {
act_btn.push('<div class="btn-group btn-group-sm">'); act_btn.push('<div class="btn-group btn-group-sm">');
act_btn.push('<button type="button" class="btn btn-warning" data-action="telnet" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_TELNET_SHELL + '"><i class="far fa-keyboard fa-fw"></i> TELNET</button>'); act_btn.push('<button type="button" class="btn btn-warning" data-action="telnet" data-id="' + acc.uni_id + '" data-acc-id="' + acc.a_id + '" data-host-id="' + acc.h_id + '" data-sub-protocol="' + TP_PROTOCOL_TYPE_TELNET_SHELL + '"><i class="far fa-keyboard fa-fw"></i> TELNET</button>');
act_btn.push('</div>'); act_btn.push('</div>');
} }
} else {
disable_msg = 'TELNET' + disable_msg;
} }
} }
h.push('<div class="remote-action-group" id =' + "account-id-" + acc.id + '">'); if (disable_msg.length > 0) {
is_disabled = true;
act_btn.push('<div class="btn-group btn-group-sm">');
act_btn.push('<button type="button" class="btn btn-disabled" disabled><i class="fa fa-ban fa-fw"></i> ');
act_btn.push(disable_msg);
act_btn.push('</button>');
act_btn.push('</div>');
}
h.push('<div>');
h.push('<div class="remote-action-group">');
h.push(act_btn.join('')); h.push(act_btn.join(''));
h.push('</div>'); h.push('</div>');
if (!is_disabled) {
h.push('<div class="remote-config">');
h.push('<button type="button" class="btn btn-default" data-action="get_config" data-acc-id=' + acc.a_id + ' data-host-id=' + acc.h_id + '><i class="fa fa-key fa-fw"></i> 获取远程连接配置</button>');
h.push('</div>');
}
h.push('</div>');
} }
return h.join(''); return h.join('');
}; };
}; };
@ -310,7 +365,7 @@ $app.on_table_host_header_created = function (header) {
}; };
$app.create_dlg_rdp_options = function () { $app.create_dlg_rdp_options = function () {
var dlg = {}; let dlg = {};
dlg.dom_id = 'dlg-rdp-options'; dlg.dom_id = 'dlg-rdp-options';
dlg.uni_id = ''; dlg.uni_id = '';
dlg.acc_id = 0; dlg.acc_id = 0;
@ -345,10 +400,10 @@ $app.create_dlg_rdp_options = function () {
dlg.dom.btn_connect.click(function () { dlg.dom.btn_connect.click(function () {
dlg.hide(); dlg.hide();
var _size_obj = $('#' + dlg.dom_id + ' input[name="screen-size"]:checked'); let _size_obj = $('#' + dlg.dom_id + ' input[name="screen-size"]:checked');
var _console = dlg.dom.console_mode.is(':checked'); let _console = dlg.dom.console_mode.is(':checked');
var _w = parseInt(_size_obj.attr('data-w')); let _w = parseInt(_size_obj.attr('data-w'));
var _h = parseInt(_size_obj.attr('data-h')); let _h = parseInt(_size_obj.attr('data-h'));
dlg.rdp_w = _w; dlg.rdp_w = _w;
dlg.rdp_h = _h; dlg.rdp_h = _h;
@ -358,7 +413,7 @@ $app.create_dlg_rdp_options = function () {
$app.connect_remote(dlg.uni_id, dlg.acc_id, dlg.host_id, dlg.protocol_type, dlg.protocol_sub_type); $app.connect_remote(dlg.uni_id, dlg.acc_id, dlg.host_id, dlg.protocol_type, dlg.protocol_sub_type);
}); });
var ops = Cookies.getJSON('rdp_options'); let ops = Cookies.getJSON('rdp_options');
dlg.rdp_w = 0; dlg.rdp_w = 0;
dlg.rdp_h = 0; dlg.rdp_h = 0;
dlg.rdp_console = false; dlg.rdp_console = false;
@ -374,7 +429,7 @@ $app.create_dlg_rdp_options = function () {
if (_.isUndefined(dlg.rdp_console)) if (_.isUndefined(dlg.rdp_console))
dlg.rdp_console = false; dlg.rdp_console = false;
var ss = [ let ss = [
{w: 800, h: 600}, {w: 800, h: 600},
{w: 1024, h: 768}, {w: 1024, h: 768},
{w: 1280, h: 1024}, {w: 1280, h: 1024},
@ -382,16 +437,16 @@ $app.create_dlg_rdp_options = function () {
{w: 1440, h: 900} {w: 1440, h: 900}
]; ];
var h = []; let h = [];
h.push('<div class="radio">'); h.push('<div class="radio">');
h.push('<div><label><input type="radio" name="screen-size" data-w="0" data-h="0"'); h.push('<div><label><input type="radio" name="screen-size" data-w="0" data-h="0"');
if (dlg.rdp_w === 0 && dlg.rdp_h === 0) if (dlg.rdp_w === 0 && dlg.rdp_h === 0)
h.push(' checked'); h.push(' checked');
h.push('> 全屏</label></div>'); h.push('> 全屏</label></div>');
for (var i = 0; i < ss.length; ++i) { for (let i = 0; i < ss.length; ++i) {
var _w = ss[i].w; let _w = ss[i].w;
var _h = ss[i].h; let _h = ss[i].h;
h.push('<div><label><input type="radio" name="screen-size" data-w="' + _w + '" data-h="' + _h + '"'); h.push('<div><label><input type="radio" name="screen-size" data-w="' + _w + '" data-h="' + _h + '"');
if (dlg.rdp_w === _w && dlg.rdp_h === _h) if (dlg.rdp_w === _w && dlg.rdp_h === _h)
h.push(' checked'); h.push(' checked');
@ -418,7 +473,7 @@ $app.create_dlg_rdp_options = function () {
dlg.protocol_type = protocol_type; dlg.protocol_type = protocol_type;
dlg.protocol_sub_type = protocol_sub_type; dlg.protocol_sub_type = protocol_sub_type;
var w = dlg.dom.dialog.width(); let w = dlg.dom.dialog.width();
x -= w / 3; x -= w / 3;
y -= 12; y -= 12;
dlg.dom.dialog.css({left: x, top: y}); dlg.dom.dialog.css({left: x, top: y});
@ -432,36 +487,61 @@ $app.create_dlg_rdp_options = function () {
return dlg; return dlg;
}; };
$app.get_remote_connection_config = function (acc_id, host_id) {
console.log(acc_id, host_id);
}
$app.connect_remote = function (uni_id, acc_id, host_id, protocol_type, protocol_sub_type) { $app.connect_remote = function (uni_id, acc_id, host_id, protocol_type, protocol_sub_type) {
var args = { let args = {
mode: 1, mode: 1,
auth_id: uni_id, auth_id: uni_id,
acc_id: acc_id, acc_id: acc_id,
host_id: host_id, host_id: host_id,
protocol_type: protocol_type, protocol_type: protocol_type,
protocol_sub_type: protocol_sub_type, protocol_sub_type: protocol_sub_type,
rdp_width: $app.dlg_rdp_options.rdp_w, is_interactive: false,
rdp_height: $app.dlg_rdp_options.rdp_h,
rdp_console: $app.dlg_rdp_options.rdp_console
}; };
if (protocol_type === TP_PROTOCOL_TYPE_RDP) {
console.log('--s--', args); args.extends({
rdp_width: $app.dlg_rdp_options.rdp_w,
rdp_height: $app.dlg_rdp_options.rdp_h,
rdp_console: $app.dlg_rdp_options.rdp_console
});
}
if (uni_id === 'none') if (uni_id === 'none')
args.mode = 2; args.mode = 2;
$assist.do_teleport( // 根据acc_id判断此远程账号是否有预设密码如果没有则需要设置interactive模式。
args, $tp.ajax_post_json('/asset/get-account-interactive-mode',
function () { {acc_id: acc_id},
// func_success function (ret) {
//$tp.notify_success('远程连接测试通过!'); console.log('ajax: /asset/get-account-interactive-mode', ret);
if (ret.code === TPE_OK) {
args.is_interactive = ret.data.is_interactive;
console.log('--s--', args);
$assist.do_teleport(
args,
function () {
// func_success
//$tp.notify_success('远程连接测试通过!');
},
function (code, message) {
if (code === TPE_NO_ASSIST)
$assist.alert_assist_not_found(code);
else
$tp.notify_error('远程连接失败:' + tp_error_msg(code, message));
}
);
} else {
$tp.notify_error('无法获取远程账号信息:' + tp_error_msg(ret.code, ret.message));
}
}, },
function (code, message) { function () {
if (code === TPE_NO_ASSIST) $tp.notify_error('网络故障,无法获取远程账号信息!');
$assist.alert_assist_not_found(code);
else
$tp.notify_error('远程连接失败:' + tp_error_msg(code, message));
} }
); );
}; };

View File

@ -822,7 +822,7 @@ $app.create_config_integration = function () {
fields: {id: 'id'} fields: {id: 'id'}
}, },
{ {
title: '服务名称', title: '外部服务名称',
key: 'name', key: 'name',
width: 120, width: 120,
}, },
@ -848,7 +848,7 @@ $app.create_config_integration = function () {
title: '', title: '',
key: 'action', key: 'action',
align: 'center', align: 'center',
width: 200, width: 150,
render: 'make_action_btn', render: 'make_action_btn',
fields: {id: 'id'} fields: {id: 'id'}
} }
@ -920,7 +920,7 @@ $app.create_config_integration = function () {
let ret = []; let ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">'); ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<btn class="btn btn-primary" data-btn-edit="edit"><i class="fa fa-edit"></i> 编辑</btn>'); ret.push('<btn class="btn btn-primary" data-btn-edit="edit"><i class="fa fa-edit"></i> 编辑</btn>');
ret.push('<btn class="btn btn-danger" data-btn-remove="' + fields.id + '"><i class="fas fa-trash-alt"></i> 删除</btn>'); ret.push('<btn class="btn btn-danger" data-btn-remove="remove"><i class="fas fa-trash-alt"></i> 删除</btn>');
ret.push('</div>'); ret.push('</div>');
return ret.join(''); return ret.join('');
}; };

View File

@ -532,7 +532,7 @@ $tp.create_table = function (options) {
if (!_tbl.options.columns.hasOwnProperty(i)) if (!_tbl.options.columns.hasOwnProperty(i))
continue; continue;
let col = _tbl.options.columns[i]; let col = _tbl.options.columns[i];
for (k in kv) { for (let k in kv) {
if (!kv.hasOwnProperty(k)) if (!kv.hasOwnProperty(k))
continue; continue;

View File

@ -412,7 +412,8 @@ $assist.do_teleport = function (args, func_success, func_error) {
session_id: session_id, session_id: session_id,
protocol_type: parseInt(args.protocol_type), protocol_type: parseInt(args.protocol_type),
protocol_sub_type: parseInt(args.protocol_sub_type), protocol_sub_type: parseInt(args.protocol_sub_type),
protocol_flag: parseInt(ret.data.protocol_flag) protocol_flag: parseInt(ret.data.protocol_flag),
is_interactive: args.is_interactive
}; };
if (args.protocol_type === TP_PROTOCOL_TYPE_RDP) { if (args.protocol_type === TP_PROTOCOL_TYPE_RDP) {

View File

@ -19,7 +19,7 @@ html {
body { body {
font-family: @font-family-normal; font-family: @font-family-normal;
//font-size: @text-size-normal; font-size: @text-size-normal;
background-color: @page-bg; background-color: @page-bg;
color: @page-color; color: @page-color;
} }

View File

@ -270,9 +270,9 @@
color: #ac4e43; color: #ac4e43;
position: absolute; position: absolute;
margin-left: -1.2em; margin-left: -1.2em;
margin-top: 1px; //margin-top: 1px;
content: "\f069"; content: "\f069";
font-size: 8px; //font-size: 8px;
font-family: 'Font Awesome 5 Free'; font-family: 'Font Awesome 5 Free';
font-weight: 900; font-weight: 900;
} }
@ -282,6 +282,11 @@
color: #999; color: #999;
} }
.control-desc-sm { .control-desc-sm {
color: #999;
padding-top: 7px;
font-size: @text-size-small;
}
.control-desc-sm-input {
color: #999; color: #999;
padding-top: 3px; padding-top: 3px;
font-size: @text-size-small; font-size: @text-size-small;

View File

@ -1,12 +1,13 @@
@charset "utf-8"; @charset "utf-8";
.remote-action-group { .remote-action-group {
display: inline-block;
margin-bottom: 3px; margin-bottom: 3px;
height: 28px; height: 28px;
.btn-group-sm > .btn { .btn-group-sm > .btn {
margin: 0; margin: 0;
padding: 6px 6px; //padding: 6px 6px;
font-size: 12px; font-size: 12px;
height: 28px; height: 28px;
min-width: 80px; min-width: 80px;
@ -14,6 +15,17 @@
&.dropdown-toggle { &.dropdown-toggle {
min-width: 0; min-width: 0;
} }
&.btn-disabled {
background-color: @color-bg-ignore;
color: #aaa;
//text-shadow: -1px -1px 1px #fff;
//& > i.fa {
// color: #b53a2f;
// text-shadow: none;
//}
}
} }
//& > ul { //& > ul {
@ -59,6 +71,7 @@
//width: 64px; //width: 64px;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
height: 28px;
&.state-disabled { &.state-disabled {
background-color: @color-bg-ignore; background-color: @color-bg-ignore;
@ -136,6 +149,7 @@
border-top-left-radius: 4px; border-top-left-radius: 4px;
border-bottom-left-radius: 4px; border-bottom-left-radius: 4px;
} }
// //
//&.remote-action-btn:first-child { //&.remote-action-btn:first-child {
// border: none; // border: none;
@ -149,6 +163,7 @@
border-top-right-radius: 4px; border-top-right-radius: 4px;
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
} }
// //
//&.remote-action-btn:last-child { //&.remote-action-btn:last-child {
// border: none; // border: none;
@ -159,9 +174,24 @@
//} //}
} }
//} //}
} }
.remote-config {
display: inline-block;
margin-left: 20px;
button {
margin: 0;
//padding: 6px 6px;
font-size: 12px;
height: 28px;
min-width: 80px;
}
}
.remote-info-group { .remote-info-group {
margin-bottom: 3px; margin-bottom: 3px;
height: 28px; height: 28px;
@ -177,49 +207,52 @@
position: relative; position: relative;
display: block; display: block;
height: 28px; height: 28px;
padding: 4px 5px; line-height: 28px;
//padding: 4px 5px;
//background-color: #efefef; //background-color: #efefef;
border-top: 1px solid #ccc; //border-top: 1px solid #ccc;
border-right: 1px solid #ccc; //border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc; //border-bottom: 1px solid #ccc;
border:none;
&.remote-action-btn { //&.remote-action-btn {
background: none; // background: none;
padding: 0; // padding: 0;
border: none; // border: none;
} //}
//
//&.remote-action-input {
// background: none;
// padding: 4px 0;
//
// select {
// border: none;
// }
//}
&.remote-action-input { //label {
background: none; // padding: 0;
padding: 4px 0; // display: block;
// float: left;
// margin-top: 1px;
// cursor: pointer;
//}
//
//select {
// margin-top: -3px;
//}
select { //&:first-child {
border: none; // border-left: 1px solid #ccc;
} // border-top-left-radius: 4px;
} // border-bottom-left-radius: 4px;
//}
label { //
padding: 0; //&:last-child {
display: block; // border-top-right-radius: 4px;
float: left; // border-bottom-right-radius: 4px;
margin-top: 1px; //}
cursor: pointer;
}
select {
margin-top: -3px;
}
&:first-child {
border-left: 1px solid #ccc;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
&:last-child {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
} }
} }
} }
@ -242,7 +275,8 @@
.title { .title {
background-color: #eee; background-color: #eee;
padding: 3px 5px; padding: 5px 5px;
font-weight: bold;
} }
.item { .item {

View File

@ -585,9 +585,9 @@ body {
// margin: 0 auto; // margin: 0 auto;
//} //}
// //
.form-group .input-group { //.form-group .input-group {
margin-bottom: 5px; // margin-bottom: 5px;
} //}
.op_box { .op_box {
display: block; display: block;

View File

@ -46,7 +46,7 @@
{% block block_body %} {% block block_body %}
<div class="page-content-inner"> <div class="page-content-inner">
{# ## 防止页面搜索框被自动填充#} {# ## 防止页面搜索框被自动填充#}
<label style="display:none;"><span></span><input type="text" name="hidden1"></label> <label style="display:none;"><span></span><input type="text" name="hidden1"></label>
<label style="display:none;"><span></span><input type="password" name="hidden2"></label> <label style="display:none;"><span></span><input type="password" name="hidden2"></label>
@ -136,12 +136,12 @@
<div class="form-horizontal"> <div class="form-horizontal">
{# ## <div class="form-group form-group-sm">#} {# ## <div class="form-group form-group-sm">#}
{# ## <label for="edit-host-type" class="col-sm-2 control-label require">主机类型:</label>#} {# ## <label for="edit-host-type" class="col-sm-2 control-label require">主机类型:</label>#}
{# ## <div class="col-sm-6">#} {# ## <div class="col-sm-6">#}
{# ## <div id="edit-host-type" class="btn-group btn-group-sm"></div>#} {# ## <div id="edit-host-type" class="btn-group btn-group-sm"></div>#}
{# ## </div>#} {# ## </div>#}
{# ## </div>#} {# ## </div>#}
<div class="form-group form-group-sm"> <div class="form-group form-group-sm">
<label for="edit-host-os-type" class="col-sm-3 control-label require">远程主机系统:</label> <label for="edit-host-os-type" class="col-sm-3 control-label require">远程主机系统:</label>
@ -303,18 +303,13 @@
<label class="col-sm-3 control-label" for="account-protocol-port"><strong>端口:</strong></label> <label class="col-sm-3 control-label" for="account-protocol-port"><strong>端口:</strong></label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="account-protocol-port" type="text" class="form-control" placeholder=""/> <input id="account-protocol-port" type="text" class="form-control" placeholder=""/>
{# ## <p id="account-protocol-port-static" class="form-control-static mono" style="color:#0a6aa1;font-weight:bold;display:none;"></p>#}
</div> </div>
</div> </div>
<div class="form-group form-group-sm"> <div class="form-group form-group-sm">
<label class="col-sm-3 control-label" for="account-auth-type"><strong>认证方式:</strong></label> <label class="col-sm-3 control-label" for="account-auth-type"><strong>认证方式:</strong></label>
<div class="col-sm-9"> <div class="col-sm-9">
<select id="account-auth-type" class="form-control"> <select id="account-auth-type" class="form-control"></select>
<option value="1">用户名/密码 认证</option>
<option value="2">SSH私钥 认证</option>
<option value="0">无需认证</option>
</select>
</div> </div>
</div> </div>
@ -358,8 +353,13 @@
<input id="account-password" type="password" class="form-control" placeholder="登录远程主机的密码"> <input id="account-password" type="password" class="form-control" placeholder="登录远程主机的密码">
<span class="input-group-btn"><button class="btn btn-sm btn-default" type="button" id="btn-show-account-password"><i class="fa fa-eye fa-fw"></i></button></span> <span class="input-group-btn"><button class="btn btn-sm btn-default" type="button" id="btn-show-account-password"><i class="fa fa-eye fa-fw"></i></button></span>
</div> </div>
<div class="control-desc-sm-input">
<span>如不填写密码,则会在远程连接时要求用户手动输入。</span>
<span id="block-clear-password">如果已设置了密码,可<a href="javascript:" id="btn-clear-password">点击此处清除</a></span>
</div>
</div> </div>
</div> </div>
</div> </div>
<div id="block-sshkey" style="display:none;"> <div id="block-sshkey" style="display:none;">

View File

@ -172,7 +172,7 @@
placeholder="用户账号,也就是用户登录名"/> placeholder="用户账号,也就是用户登录名"/>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="control-desc">英文字符和数字最大32字符</div> <div class="control-desc-sm">英文字符和数字最大32字符</div>
</div> </div>
</div> </div>
@ -189,7 +189,7 @@
<input id="edit-user-email" type="text" class="form-control" placeholder="电子邮箱地址"/> <input id="edit-user-email" type="text" class="form-control" placeholder="电子邮箱地址"/>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="control-desc">用于激活账号、重置密码。</div> <div class="control-desc-sm">用于激活账号、重置密码。</div>
</div> </div>
</div> </div>
@ -224,7 +224,7 @@
</div> </div>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="control-desc">开始</div> <div class="control-desc-sm">开始时间</div>
</div> </div>
</div> </div>
<div class="form-group form-group-sm"> <div class="form-group form-group-sm">
@ -237,7 +237,7 @@
</div> </div>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="control-desc">结束</div> <div class="control-desc-sm">结束时间</div>
</div> </div>
</div> </div>
@ -444,7 +444,7 @@
placeholder="LDAP服务器IP或域名"/> placeholder="LDAP服务器IP或域名"/>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label class="form-check-label"><input id="edit-ldap-ssl" type="checkbox" class="form-check-input"/> 使用 SSL</label> <label class="control-label"><input id="edit-ldap-ssl" type="checkbox"/> 使用 SSL</label>
</div> </div>
</div> </div>
@ -503,7 +503,7 @@
<label for="edit-ldap-base-dn" class="col-sm-2 control-label require">用户基准DN</label> <label for="edit-ldap-base-dn" class="col-sm-2 control-label require">用户基准DN</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="edit-ldap-base-dn" type="text" class="form-control" placeholder=""/> <input id="edit-ldap-base-dn" type="text" class="form-control" placeholder=""/>
<div class="control-desc-sm">限制用户DN的范围例如 <span class="important">ou=dev,ou=company,ou=com</span> <div class="control-desc-sm-input">限制用户DN的范围例如 <span class="important">ou=dev,ou=company,ou=com</span>
</div> </div>
</div> </div>
</div> </div>
@ -513,7 +513,7 @@
<div class="col-sm-9"> <div class="col-sm-9">
<input id="edit-ldap-filter" type="text" class="form-control" placeholder="" <input id="edit-ldap-filter" type="text" class="form-control" placeholder=""
value="(&(objectClass=person))"/> value="(&(objectClass=person))"/>
<div class="control-desc-sm">列举用户时的过滤器,例如 <span class="important">(&(objectClass=person))</span> <div class="control-desc-sm-input">列举用户时的过滤器,例如 <span class="important">(&(objectClass=person))</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -109,7 +109,7 @@ class TPAssistBridge(object):
return assist_info return assist_info
def handle_assist_message(self, msg_req: AssistMessage): def handle_assist_message(self, msg_req: AssistMessage):
log.v('add message, cmd_id={}\n'.format(msg_req.cmd_id)) # log.v('add message, cmd_id={}\n'.format(msg_req.cmd_id))
self._commands[msg_req.cmd_id] = msg_req self._commands[msg_req.cmd_id] = msg_req
def on_web_client_connect(self, msg_req: AssistMessage, s_id: str, param: dict) -> None: def on_web_client_connect(self, msg_req: AssistMessage, s_id: str, param: dict) -> None:

View File

@ -126,6 +126,10 @@ controllers = [
(r'/asset/account-group/(.*)', account.AccGroupInfoHandler), (r'/asset/account-group/(.*)', account.AccGroupInfoHandler),
# - [json] 添加/更新 远程账号 # - [json] 添加/更新 远程账号
(r'/asset/update-account', account.DoUpdateAccountHandler), (r'/asset/update-account', account.DoUpdateAccountHandler),
# - [json] 清除 远程账号的预设密码
(r'/asset/clear-account-password', account.DoClearAccountPasswordHandler),
# - [json] 查询 远程账号是否有预设密码
(r'/asset/get-account-interactive-mode', account.DoGetAccountInteractiveModeHandler),
# - [json] 禁用/解禁/删除 远程账号 # - [json] 禁用/解禁/删除 远程账号
(r'/asset/update-accounts', account.DoUpdateAccountsHandler), (r'/asset/update-accounts', account.DoUpdateAccountsHandler),
# - [json] 获取账号列表 # - [json] 获取账号列表

View File

@ -233,15 +233,15 @@ class DoUpdateAccountHandler(TPBaseJsonHandler):
if acc_id == -1: if acc_id == -1:
# 新增账号 # 新增账号
if param['auth_type'] == TP_AUTH_TYPE_PASSWORD and len(param['password']) == 0: # if param['auth_type'] == TP_AUTH_TYPE_PASSWORD and len(param['password']) == 0:
return self.write_json(TPE_PARAM) # return self.write_json(TPE_PARAM)
elif param['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY and len(param['pri_key']) == 0: if param['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY and len(param['pri_key']) == 0:
return self.write_json(TPE_PARAM) return self.write_json(TPE_PARAM)
if param['auth_type'] == TP_AUTH_TYPE_PASSWORD and len(param['password']) > 0: if param['auth_type'] == TP_AUTH_TYPE_PASSWORD and len(param['password']) > 0:
code, ret_data = yield core_service_async_enc(param['password']) code, ret_data = yield core_service_async_enc(param['password'])
if code != TPE_OK: if code != TPE_OK:
return self.write_json(code) return self.write_json(code, '无法加密存储密码!')
else: else:
param['password'] = ret_data param['password'] = ret_data
elif param['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY and len(param['pri_key']) > 0: elif param['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY and len(param['pri_key']) > 0:
@ -260,6 +260,60 @@ class DoUpdateAccountHandler(TPBaseJsonHandler):
self.write_json(err, data=info) self.write_json(err, data=info)
class DoClearAccountPasswordHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_ACCOUNT)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
host_id = int(args['host_id'])
acc_id = int(args['acc_id'])
except:
log.e('\n')
return self.write_json(TPE_PARAM)
err = account.clear_account_password(self, host_id, acc_id)
self.write_json(err)
class DoGetAccountInteractiveModeHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_OPS)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
acc_id = int(args['acc_id'])
except:
log.e('\n')
return self.write_json(TPE_PARAM)
err, password = account.get_account_password(acc_id)
if err != TPE_OK:
return self.write_json(err)
self.write_json(TPE_OK, data={'is_interactive': True if len(password) == 0 else False})
class DoUpdateAccountsHandler(TPBaseJsonHandler): class DoUpdateAccountsHandler(TPBaseJsonHandler):
@tornado.gen.coroutine @tornado.gen.coroutine
def post(self): def post(self):

View File

@ -421,9 +421,9 @@ class DoGetSessionIDHandler(TPBaseJsonHandler):
conn_info['_enc'] = 0 conn_info['_enc'] = 0
if acc_id == -1: if acc_id == -1:
if auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0: # if auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0:
return self.write_json(TPE_PARAM) # return self.write_json(TPE_PARAM)
elif auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0: if auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0:
return self.write_json(TPE_PARAM) return self.write_json(TPE_PARAM)
else: else:
if (auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0) or (auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0): if (auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0) or (auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0):

View File

@ -61,7 +61,7 @@ class AssistHandler(tornado.websocket.WebSocketHandler):
'method': msg.method, 'method': msg.method,
'param': param 'param': param
} }
log.w('send ws request: {}\n'.format(json_encode(data))) log.d('send ws request: {}\n'.format(json_encode(data)))
self.write_message(json_encode(data)) self.write_message(json_encode(data))
def send_response(self, msg: AssistMessage, code, message='', data=None): def send_response(self, msg: AssistMessage, code, message='', data=None):
@ -75,7 +75,7 @@ class AssistHandler(tornado.websocket.WebSocketHandler):
'message': message, 'message': message,
'data': data 'data': data
} }
log.w('send ws response: {}\n'.format(json_encode(ret))) log.d('send ws response: {}\n'.format(json_encode(ret)))
self.write_message(json_encode(ret)) self.write_message(json_encode(ret))
def set_assist_id(self, assist_id: int) -> None: def set_assist_id(self, assist_id: int) -> None:

View File

@ -296,6 +296,32 @@ def add_account(handler, host_id, args):
return TPE_OK, _id return TPE_OK, _id
def clear_account_password(handler, host_id, acc_id):
db = get_db()
sql = 'UPDATE `{tp}acc` SET `password`="" WHERE `id`={ph} AND `host_id`={ph}'.format(tp=db.table_prefix, ph=db.place_holder)
db_ret = db.exec(sql, (acc_id, host_id))
if not db_ret:
return TPE_DATABASE
return TPE_OK
def get_account_password(acc_id):
db = get_db()
s = SQL(db)
s.select_from('acc', ['password'], alt_name='a')
s.where('a.id={ph}'.format(ph=db.place_holder))
err = s.query((acc_id, ))
if err != TPE_OK:
return err, None
if len(s.recorder) != 1:
return TPE_DATABASE, None
# s.recorder[0]['_host'] = sh.recorder[0]
return TPE_OK, s.recorder[0]['password']
def update_account(handler, host_id, acc_id, args): def update_account(handler, host_id, acc_id, args):
""" """
更新一个远程账号 更新一个远程账号