修正被锁定的用户仍然可以登录;修正录像文件中记录的起始时间不正确;增加ssh回放界面显示会话详细信息;

pull/32/head
apexliu 2017-04-16 06:15:07 +08:00
parent 43a42f863e
commit 59f14d3e73
33 changed files with 1494 additions and 1950 deletions

View File

@ -16,9 +16,6 @@
<link href="plugins/gritter/css/jquery.gritter.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet" type="text/css"/>
<!--<link href="css/desktop.css" rel="stylesheet" type="text/css"/>-->
<!--<link href="${ static_url('css/main.css') }" rel="stylesheet" type="text/css"/>-->
</head>
<body>
@ -33,7 +30,7 @@
<div class="footer">
<div class="container">
<p>触维软件旗下产品 | TELEPORT | &copy;2015 - 2016 <a href="http://www.eomsoft.net/" target="_blank">触维软件</a>,保留所有权利。</p>
<p>触维软件旗下产品 | TELEPORT | &copy;2015 - 2017 <a href="http://teleport.eomsoft.net/" target="_blank">触维软件</a>,保留所有权利。</p>
</div>
</div>
@ -82,21 +79,6 @@
</div>
</div>
<!--<div class="form-group form-group-sm">-->
<!--<div class="col-sm-1"></div>-->
<!--<div class="col-sm-6">-->
<!--<div class="arg-detail">-->
<!--<span>命令参数中需要传递主机信息和登录信息,可以用以下变量替换(注意大小写!):</span>-->
<!--<ul>-->
<!--<li><strong>{host_ip}</strong> 替换主机IP地址</li>-->
<!--<li><strong>{host_port}</strong> 替换主机端口号</li>-->
<!--<li><strong>{user_name}</strong> 替换用户名</li>-->
<!--<li><strong>{real_ip}</strong> 替换远程主机真实IP仅用于显示</li>-->
<!--</ul>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<div class="form-group form-group-sm">
<div class="col-sm-1"></div>
<div class="col-sm-6">

View File

@ -44,12 +44,15 @@ End Sub
ubuntuLinuxSecureCRT
*/
//#define RDP_CLIENT_SYSTEM_BUILTIN
// #define RDP_CLIENT_SYSTEM_BUILTIN
// #define RDP_CLIENT_SYSTEM_ACTIVE_CONTROL
#define RDP_CLIENT_FREERDP
#ifdef RDP_CLIENT_SYSTEM_BUILTIN
#include <WinCrypt.h>
#pragma comment(lib, "Crypt32.lib")
std::string rdp_content = "\
connect to console:i:%d\n\
screen mode id:i:%d\n\
@ -87,6 +90,7 @@ redirectposdevices:i:0\n\
redirectdirectx:i:0\n\
autoreconnection enabled:i:0\n\
drivestoredirect:s:*\n\
password 51:b:%s\n\
";
//password 51:b:01000000D08C9DDF0115D1118C7A00C04FC297EB0100000052A9E191EA75A948B359790578C9371A0000000008000000700073007700000003660000A8000000100000000A1DCCD2E50775CA25EC3857164B34DC0000000004800000A000000010000000FCE1A645B9B61AA450946BB6F955058108020000D83591CA47562D6DDAA689F050AE145039EBE22E00D1D3AEAA98373C7B63C3E8E7149072DF989EA43EFCE20513AD3D27B11BE7F17066A688E1DCE828AF85460AAC327B38E90776DB962888E4393D19637578984B19A187AAD95F6D2726ADE7DD315FF56C15FF5B3031014EDDCC3C24D1B81779AFDB006EE575F5BEFB8D2D2138D9D9D642BBB251CC5ED7226968764856EC660A646BACE748A13D6002A9A537AA70710615650B9387EED66DE28BD57B304BBDD7B581B943DA628EB0289E30A8BA784B76F7885BECCAB4FEF7820E97EE3C6E036EEAF6EAA669288DF2FCACC9BEC045C907EBBDE87AFB8CC6B07A600BD63AC891B61D95C2265DD9FD5E635D61BFBF5EDC28311375066611C610FB533D64515B643C82F57D9B183B05C156D91BC0974D38E546022B139E82452E6F1EDF76E52F732C3904E5E433F8F3D488DB0698427DBB0791A9F207F8CB6654CB8410BAF4A59C4F9E821E589ABC1E6E6E1D432181B690408F6884FE1007895A4D26D4A5A2C7458EE747DA35D44AC9FB08AB5477EA3E7CCDB3E37EE20FAFD0D0CF9584E420598B7003B347943AC28048F45E0FD21AD08148FFADCE0E7877219259A7BE722FFAE845A429BA2CF0A71F2D19EA7495530FABDB5106E8D404A38A7E6394C38457640EA7398C5D55F0C4D342CC6A39C77E10A2A5145AEA40B14F5C7C3760334D83C9BE748383FADE231248537353817D51F7B44F61B406ABC61400000071C354139F458B02D978015F785B97F7F6B307380\n\
@ -155,6 +159,34 @@ int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_f
return i >= src_len ? j : -1;
}
#ifdef RDP_CLIENT_SYSTEM_BUILTIN
bool calc_psw51b(const char* password, std::string& ret)
{
DATA_BLOB DataIn;
DATA_BLOB DataOut;
ex_wstr w_pswd;
ex_astr2wstr(password, w_pswd, EX_CODEPAGE_ACP);
DataIn.cbData = w_pswd.length() * sizeof(wchar_t);
DataIn.pbData = (BYTE*)w_pswd.c_str();
if (!CryptProtectData(&DataIn, L"psw", NULL, NULL, NULL, 0, &DataOut))
return false;
char szRet[5] = {0};
for (int i = 0; i < DataOut.cbData; ++i)
{
sprintf_s(szRet, 5, "%02X", DataOut.pbData[i]);
ret += szRet;
}
LocalFree(DataOut.pbData);
return true;
}
#endif
TsHttpRpc::TsHttpRpc()
{
m_stop = false;
@ -742,12 +774,21 @@ void TsHttpRpc::_rpc_func_create_ts_client(const ex_astr& func_args, ex_astr& bu
int split_pos = sid.length() - 2;
std::string real_sid = sid.substr(0, split_pos);
std::string psw51b;
if (!calc_psw51b("Abcd1234", psw51b))
{
printf("calc password failed.\n");
_create_json_ret(buf, TPE_FAILED);
return;
}
char sz_rdp_file_content[4096] = { 0 };
sprintf_s(sz_rdp_file_content, rdp_content.c_str(),
console, display, width, higth
, cx, cy, cx + width + 20, cy + higth + 40
, teleport_ip.c_str(), teleport_port
, real_sid.c_str()
, psw51b.c_str()
);
char sz_file_name[MAX_PATH] = { 0 };

View File

@ -27,8 +27,8 @@
#define TPE_UNKNOWN_CMD 124 // 未知的命令
#define TPE_JSON_FORMAT 125 // 错误的JSON格式需要JSON格式数据但是却无法按JSON格式解码
#define TPE_PARAM 126 // 参数错误
#define TPE_DATA 127 // 数据错误
#define TPE_PARAM 126 // 参数错误
#define TPE_DATA 127 // 数据错误
@ -40,9 +40,9 @@
//-------------------------------------------------------
// 助手程序专用错误值
//-------------------------------------------------------
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
#define TPE_OLD_ASSIST 100001 // 助手程序版本太低
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)

View File

@ -5,238 +5,6 @@
#include "base_record.h"
#if 0
base_record::base_record()
{
//g_env.m_record_ssh_path
m_buf = new unsigned char[MAX_SIZE_PER_FILE];
memset(m_buf, 0, MAX_SIZE_PER_FILE);
m_buf_offset = 0;
m_begin_time = 0;
m_last_time = 0;
m_file_current_index = 0;
m_current_file = 0;
m_totol_size = 0;
}
base_record::~base_record()
{
if (NULL != m_buf)
{
delete[] m_buf;
m_buf = NULL;
}
}
void base_record::begin(int record_id, int record_type)
{
char szPath[1024] = { 0 };
ex_astr ssh_path;
m_begin_time = ex_get_tick_count();
m_last_time = m_begin_time;
m_file_current_index = 0;
m_current_file = 0;
if (record_type == 2)
{
//ex_mkdirs()
#ifdef EX_OS_WIN32
ts_str2astr(g_env.m_record_ssh_path, ssh_path);
sprintf_s(szPath, "%s\\%d\\", ssh_path.c_str(), record_id);
int ret = _mkdir(szPath);
#else
ssh_path = g_env.m_record_ssh_path;
snprintf(szPath, 1024, "%s/%d", ssh_path.c_str(), record_id);
EXLOGV("try to create folder for record: [%s]\n", szPath);
int status = mkdir(szPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
EXLOGV("create folder for record return %d, errno=%d.\n", status, errno);
#endif
m_current_path = szPath;
open_next_file();
}
}
void base_record::end()
{
ex_u64 current_time = ex_get_tick_count();
ex_u64 internal_time = m_last_time - m_begin_time;
save_buffer_to_file(int(internal_time));
if (m_buf)
{
delete[] m_buf;
m_buf = NULL;
}
if (m_current_file)
{
fclose(m_current_file);
}
ts_replay_header header = {0};
ex_strcpy(header.ID, 16, "teleport");
ex_strcpy(header.version, 16, "1.0.0.1");
header.total_time = (ex_u32)internal_time;
header.total_file_count = (ex_u8)m_file_current_index;
header.total_size = (ex_u8)m_totol_size;
int ts_replay_header_len = sizeof(ts_replay_header);
char szPath[1024] = { 0 };
#ifdef EX_OS_WIN32
sprintf_s(szPath, "%s\\head.init", m_current_path.c_str());
#else
snprintf(szPath, 1024, "%s/head.init", m_current_path.c_str());
#endif
FILE* f = NULL;
if ((f = fopen(szPath, "wb")) == NULL) /* open file TEST.$$$ */
{
return;
}
int ret = fwrite(&header, sizeof(ts_replay_header), 1, f);
ret = fwrite(&m_timelist[0], m_timelist.size() * sizeof(int), 1, f);
fclose(f);
char szTermPath[1024] = { 0 };
#ifdef EX_OS_WIN32
sprintf_s(szTermPath, "%s\\term.init", m_current_path.c_str());
#else
snprintf(szTermPath, 1024, "%s/term.init", m_current_path.c_str());
#endif
if ((f = fopen(szTermPath, "wb")) == NULL)
{
return;
}
ssh_terms_data_header terms_header = { 0 };
ex_strcpy(terms_header.ID, 16,"teleport");
ex_strcpy(terms_header.version, 16,"1.0.0.1");
terms_header.term_count = (ex_u32)m_windows_size_list.size();
ret = fwrite(&terms_header,sizeof(ssh_terms_data_header), 1, f);
if (m_windows_size_list.size() > 0)
{
ret = fwrite(&m_windows_size_list[0], m_windows_size_list.size() * sizeof(ssh_terms_data), 1, f);
}
fclose(f);
}
void base_record::windows_size(ssh_terms_data size_info)
{
ex_u64 internal_time = ex_get_tick_count() - m_begin_time;
size_info.time = (ex_u32)internal_time;
m_windows_size_list.push_back(size_info);
}
void base_record::record(unsigned char* buf, int len, int cmd)
{
ex_u64 current_time = ex_get_tick_count();
ex_u64 internal_time = current_time - m_begin_time;
m_last_time = current_time;
//bool bSwitchFile = false;
//bool bWriteFile = false;
ts_replay_data_header replay_header = {0};
replay_header.action = (ex_u8)cmd;
replay_header.time = (ex_u32)internal_time;
replay_header.size = (ex_u32)len;
//int header_len = sizeof(ts_replay_data_header);
bool bRet = cached_buffer(&replay_header, buf, len);
if (!bRet)
{
//缓存已满,把缓存存文件,并且清空缓存
save_buffer_to_file(int(internal_time));
//打开下个文件
open_next_file();
bRet = cached_buffer(&replay_header, buf, len);
if (!bRet)
{
//如果还是太大,不能缓存,直接存文件
save_to_file(ex_u32(internal_time), &replay_header, buf, len);
open_next_file();
}
}
}
bool base_record::cached_buffer(ts_replay_data_header* header, unsigned char* buf, int len)
{
size_t header_len = sizeof(ts_replay_data_header);
if ((m_buf_offset + len + header_len) > MAX_SIZE_PER_FILE)
{
return false;
}
//长度够长直接存缓存
memcpy(m_buf + m_buf_offset, header, header_len);
m_buf_offset += header_len;
memcpy(m_buf + m_buf_offset, buf, len);
m_buf_offset += len;
return true;
}
bool base_record::open_next_file()
{
char szPath[1024] = { 0 };
#ifdef EX_OS_WIN32
sprintf_s(szPath, "%s\\%d.ts", m_current_path.c_str(), m_file_current_index);
#else
snprintf(szPath, 1024, "%s/%d.ts", m_current_path.c_str(), m_file_current_index);
#endif
if (NULL != m_current_file)
{
fclose(m_current_file);
}
if ((m_current_file = fopen(szPath, "wb")) == NULL) /* open file TEST.$$$ */
{
return false;
}
m_file_current_index++;
return true;
}
bool base_record::save_buffer_to_file(int internal_time)
{
if(NULL == m_current_file)
return false;
int ret = fwrite(m_buf, m_buf_offset, 1, m_current_file); /* 写的struct文件*/
m_totol_size += m_buf_offset;
m_buf_offset = 0;
m_timelist.push_back(ex_u32(internal_time));
return true;
}
bool base_record::save_to_file(int internal_time,ts_replay_data_header* header, unsigned char* buf, int len)
{
if(NULL == m_current_file)
return false;
int ret = fwrite(header, sizeof(ts_replay_data_header), 1, m_current_file);
ret = fwrite(buf, len, 1, m_current_file);
m_totol_size += sizeof(ts_replay_data_header);
m_totol_size += len;
m_timelist.push_back(ex_u32(internal_time));
return true;
}
#endif
//====================================================
// NEW INTERFACE
//====================================================
TppRecBase::TppRecBase()
{
m_cache.reserve(MAX_SIZE_PER_FILE);

View File

@ -21,7 +21,7 @@ void TppSshRec::_on_begin(const TPP_SESSION_INFO* info)
{
if (NULL == info)
return;
m_head.timestamp = time(NULL);
m_head.port = info->host_port;
// memcpy(m_head.account, info.account_name.c_str(), info.account_name.length() > 15 ? 15 : info.account_name.length());
// memcpy(m_head.username, info.user_name.c_str(), info.user_name.length() > 15 ? 15 : info.user_name.length());
@ -41,7 +41,7 @@ void TppSshRec::_on_end(void)
_save_to_cmd_file();
// ¸üÐÂÍ·ÐÅÏ¢
m_head.timestamp = m_start_time;
//m_head.timestamp = m_start_time;
m_head.time_ms = (ex_u32)(m_last_time - m_start_time);
ex_wstr fname = m_base_path;

View File

@ -58,12 +58,14 @@ class VerifyUser(TPBaseJsonHandler):
return
try:
user_id, account_type, nickname = user.verify_user(username, userpwd)
user_id, account_type, nickname, locked = user.verify_user(username, userpwd)
if locked == 1:
return self.write_json(-1, '账号被锁定,请联系管理员!')
if user_id == 0:
if cfg.app_mode == APP_MODE_MAINTENANCE:
self.write_json(-2, '系统维护中,请稍候再试')
self.write_json(-2, '系统维护中,请稍候再试')
else:
self.write_json(-1, '用户名/密码错误')
self.write_json(-1, '用户名/密码错误')
return
_user = self.get_session('user')
@ -92,7 +94,7 @@ class VerifyUser(TPBaseJsonHandler):
except:
log.e('can not set session.')
self.write_json(-1, '无法记录用户登录状态')
self.write_json(-1, '无法记录用户登录状态')
class LogoutHandler(TPBaseUserAuthHandler):

View File

@ -513,22 +513,19 @@ class DeleteCert(TPBaseUserAuthJsonHandler):
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
# print('args', args)
else:
# ret = {'code':-1}
self.write_json(-1)
return
return self.write_json(-1)
cert_id = args['cert_id']
try:
ret = host.delete_cert(cert_id)
if ret:
self.write_json(0)
return self.write_json(0)
else:
self.write_json(-1)
return
return self.write_json(-2)
except:
self.write_json(-1)
return
return self.write_json(-3)
class UpdateCert(TPBaseUserAuthJsonHandler):

View File

@ -414,7 +414,7 @@ def add_cert(cert_pub, cert_pri, cert_name):
def delete_cert(cert_id):
db = get_db()
sql = 'DELETE FROM `{}key` WHERE `cert_id`={};'.format(int(cert_id))
sql = 'DELETE FROM `{}key` WHERE `cert_id`={};'.format(db.table_prefix, int(cert_id))
return db.exec(sql)

View File

@ -19,8 +19,12 @@ def read_record_head(record_id):
data = file.read()
offset = 0
magic, = struct.unpack_from('I', data, offset) # magic must be 1381126228, 'TPRR'
magic, = struct.unpack_from('I', data, offset) # magic must be 1381126228, 'TPPR'
offset += 4
ver, = struct.unpack_from('H', data, offset)
offset += 2
protocol, = struct.unpack_from('H', data, offset)
offset += 2
time_start, = struct.unpack_from('Q', data, offset)
offset += 8
pkg_count, = struct.unpack_from('I', data, offset)
@ -42,6 +46,11 @@ def read_record_head(record_id):
user_name, = struct.unpack_from('16s', data, offset)
user_name = user_name.decode()
offset += 16
ip, = struct.unpack_from('18s', data, offset)
ip = ip.decode()
offset += 18
port, = struct.unpack_from('H', data, offset)
offset += 2
except Exception as e:
return None
@ -50,81 +59,19 @@ def read_record_head(record_id):
file.close()
header = dict()
header['start'] = time_start
header['file_count'] = file_count
header['time_used'] = time_used
header['width'] = width
header['height'] = height
header['account'] = account
header['user_name'] = user_name
header['ip'] = ip
header['port'] = port
return header
# def read_record_term(record_id):
# record_path = os.path.join(cfg.core.replay_path, 'ssh', '{}'.format(record_id))
# term_file_path = os.path.join(record_path, 'term.init')
# # term_file_path = r"E:\GitWork\teleport\share\data\replay\ssh\103\term.init"
#
# file = None
# try:
# file = open(term_file_path, 'rb')
# data = file.read()
# x = len(data)
# offset = 0
# # data = data.decode()
# ID, = struct.unpack_from('16s', data, offset)
# ID = ID.decode()
# offset += 16
#
# Version, = struct.unpack_from('16s', data, offset)
# Version = Version.decode()
# offset += 16
#
# t_count, = struct.unpack_from('I', data, offset)
# offset += 4
# term_list = list()
# for i in range(t_count):
# # _term, = struct.unpack_from('16s', data, offset)
# # _term = _term.decode()
# # offset += 16
# _time, = struct.unpack_from('I', data, offset)
# offset += 4
#
# x, = struct.unpack_from('I', data, offset)
# offset += 4
#
# y, = struct.unpack_from('I', data, offset)
# offset += 4
#
# # px, = struct.unpack_from('I', data, offset)
# # offset += 4
# #
# # py, = struct.unpack_from('I', data, offset)
# # offset += 4
# #
# # _time, = struct.unpack_from('I', data, offset)
# # offset += 4
# temp = dict()
# # temp['term'] = _term
# temp['t'] = _time
# temp['w'] = x
# temp['h'] = y
# # temp['px'] = px
# # temp['py'] = py
#
# term_list.append(temp)
#
# except Exception as e:
# return None
# finally:
# if file is not None:
# file.close()
#
# header = dict()
# header['id'] = ID
# header['ver'] = Version
# header['count'] = t_count
# header['term_list'] = term_list
# return header
def read_record_info(record_id, file_id):
record_path = os.path.join(app_cfg().core.replay_path, 'ssh', '{:06d}'.format(int(record_id)))
file_info = os.path.join(record_path, 'tp-ssh.{:03d}'.format(int(file_id)))

View File

@ -12,7 +12,7 @@ def verify_user(name, password):
cfg = app_cfg()
db = get_db()
sql = 'SELECT `account_id`, `account_type`, `account_name`, `account_pwd` FROM `{}account` WHERE `account_name`="{}";'.format(db.table_prefix, name)
sql = 'SELECT `account_id`, `account_type`, `account_name`, `account_pwd`, `account_lock` FROM `{}account` WHERE `account_name`="{}";'.format(db.table_prefix, name)
db_ret = db.query(sql)
if db_ret is None:
# 特别地,如果无法取得数据库连接,有可能是新安装的系统,尚未建立数据库,此时应该处于维护模式
@ -20,25 +20,29 @@ def verify_user(name, password):
if cfg.app_mode == APP_MODE_MAINTENANCE:
if name == 'admin' and password == 'admin':
return 1, 100, 'admin'
return 0, 0, ''
return 0, 0, '', 0
if len(db_ret) != 1:
return 0, 0, ''
return 0, 0, '', 0
user_id = db_ret[0][0]
account_type = db_ret[0][1]
name = db_ret[0][2]
locked = db_ret[0][4]
if locked == 1:
return 0, 0, '', locked
if not sec_verify_password(password, db_ret[0][3]):
# 按新方法验证密码失败,可能是旧版本的密码散列格式,再尝试一下
if db_ret[0][3] != hashlib.sha256(password.encode()).hexdigest():
return 0, 0, ''
return 0, 0, '', locked
else:
# 发现此用户的密码散列格式还是旧的,更新成新的吧!
_new_sec_password = sec_generate_password(password)
sql = 'UPDATE `{}account` SET `account_pwd`="{}" WHERE `account_id`={}'.format(db.table_prefix, _new_sec_password, int(user_id))
db.exec(sql)
return user_id, account_type, name
return user_id, account_type, name, locked
def modify_pwd(old_pwd, new_pwd, user_id):

View File

@ -1 +1 @@
@charset "utf-8";body{padding-top:70px;padding-bottom:24px;background-color:#ececed}#head nav.navbar{height:70px;line-height:70px;background-color:#333;color:#fff}#head .logo .desc{display:block;float:right;color:#ccc;margin-top:10px;font-size:18px}#foot nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#ddd;color:#fff;font-size:12px;border-top:1px solid #ccc}#foot nav.navbar .container{height:24px}#foot nav.navbar p{margin:0 auto;text-align:center;color:#333}#content{margin:10px 0 50px 0}.auth-box{margin-top:30px;min-height:120px;border:1px solid #ccc;border-radius:8px;background-color:rgba(255,255,255,0.6)}.auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid #ccc}.auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#999}.auth-box .header .selected{border-bottom:1px solid #69c;color:#555}.auth-box .header .title:hover{border-bottom:1px solid #999}.auth-box .inputarea{margin:30px}.auth-box .inputarea .input-group-addon{padding:0 5px 0 5px}.auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#999}#leftside{width:560px;height:560px;padding-top:60px;background:url(../img/login/side-001.jpg) 0 0 no-repeat}#leftside h1{font-size:24px;color:#888}#leftside p{font-size:18px;color:#888;padding-left:24px}.auth-box .inputbox{margin-bottom:10px}.auth-box-lg .inputbox{margin-bottom:20px}.auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box .op_error{background:#fbb}.auth-box .op_wait{background:#ccc}.auth-box .quick-area{padding:80px 0 80px 0}.auth-box .quick-area .quick-disc{text-align:center;margin-bottom:20px}.auth-box .quick-area .quick-no{padding-top:80px;padding-bottom:100px}.auth-box .quick-area .quick-yes{text-align:center}.auth-box .quick-area .quick-yes .quick-account{display:inline-block;margin:auto;margin-bottom:20px}.auth-box .quick-area .quick-yes .quick-account:hover .quick-image{box-shadow:0 0 8px #00c2f6}.auth-box .quick-area .quick-yes .quick-image{display:block;width:82px;height:82px;line-height:80px;font-size:64px;margin:auto;border:1px solid #a4cdf6;box-shadow:0 0 6px #a7d1fb}.auth-box .quick-area .quick-yes .quick-name{display:block;margin-top:5px}
@charset "utf-8";body{padding-top:70px;padding-bottom:24px;background-color:#ececed}#head nav.navbar{height:70px;line-height:70px;background-color:#333;color:#fff}#head .logo .desc{display:block;float:right;color:#ccc;margin-top:10px;font-size:18px}#foot nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#ddd;color:#fff;font-size:12px;border-top:1px solid #ccc}#foot nav.navbar .container{height:24px}#foot nav.navbar p{margin:0 auto;text-align:center;color:#333}#content{margin:10px 0 50px 0}.auth-box{margin-top:30px;min-height:120px;border:1px solid #ccc;border-radius:8px;background-color:rgba(255,255,255,0.6)}.auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid #ccc}.auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#999}.auth-box .header .selected{border-bottom:1px solid #69c;color:#555}.auth-box .header .title:hover{border-bottom:1px solid #999}.auth-box .inputarea{margin:30px}.auth-box .inputarea .input-group-addon{padding:0 5px 0 5px}.auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#999}#leftside{width:560px;height:560px;padding-top:60px;background:url(../img/login/side-001.jpg) 0 0 no-repeat}@media screen and (max-width:990px){#leftside{display:none}}#leftside h1{font-size:24px;color:#888}#leftside p{font-size:18px;color:#888;padding-left:24px}.auth-box .inputbox{margin-bottom:10px}.auth-box-lg .inputbox{margin-bottom:20px}.auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box .op_error{background:#fbb}.auth-box .op_wait{background:#ccc}.auth-box .quick-area{padding:80px 0 80px 0}.auth-box .quick-area .quick-disc{text-align:center;margin-bottom:20px}.auth-box .quick-area .quick-no{padding-top:80px;padding-bottom:100px}.auth-box .quick-area .quick-yes{text-align:center}.auth-box .quick-area .quick-yes .quick-account{display:inline-block;margin:auto;margin-bottom:20px}.auth-box .quick-area .quick-yes .quick-account:hover .quick-image{box-shadow:0 0 8px #00c2f6}.auth-box .quick-area .quick-yes .quick-image{display:block;width:82px;height:82px;line-height:80px;font-size:64px;margin:auto;border:1px solid #a4cdf6;box-shadow:0 0 6px #a7d1fb}.auth-box .quick-area .quick-yes .quick-name{display:block;margin-top:5px}

File diff suppressed because it is too large Load Diff

View File

@ -522,10 +522,10 @@ ywl.on_user_host_table_created = function (tbl) {
ywl.ajax_post_json('/user/delete-host', {host_list: host_list, user_name: ywl.page_options.user_name},
function (ret) {
tbl.remove_row(row_id);
ywl.notify_success('删除用户拥有主机成功');
ywl.notify_success('回收授权成功!');
},
function () {
ywl.notify_error('删除用户拥有主机失败');
ywl.notify_error('回收授权失败!');
}
);
};

View File

@ -25,23 +25,23 @@ ywl.create_app = function () {
$('#captcha_image').click(function () {
$(this).attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha').focus();
$('#captcha').focus().val('');
});
$('#username_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
if (event.which === 13) {
$('#password_account').focus();
}
});
$('#password_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
if (event.which === 13) {
$('#captcha').focus();
}
});
$('#captcha').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
if (event.which === 13) {
_app.login_account();
}
});
@ -64,7 +64,6 @@ ywl.create_app = function () {
str_password = dom_password.val();
str_captcha = dom_captcha.val();
is_remember = dom_remember.is(':checked');
console.log('xxxx', is_remember);
if (str_username.length === 0) {
show_op_box('error', '缺少账号!');
@ -92,7 +91,7 @@ ywl.create_app = function () {
// 先判断一下captcha是否正确如果不正确拒绝登录
ywl.ajax_post_json('/auth/verify-captcha', {captcha: str_captcha},
function (ret) {
if (ret.code === 0) {
if (ret.code === TPE_OK) {
// 验证成功
hide_op_box();
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在登录TELEPORT请稍候...');
@ -116,14 +115,11 @@ ywl.create_app = function () {
};
_app.do_account_login = function (username, userpwd, captcha, is_remember) {
console.log('remember', is_remember);
ywl.ajax_post_json('/auth/verify-user', {username: username, userpwd: userpwd, captcha: captcha, remember: is_remember},
function (ret) {
if (ret.code == 0) {
// 验证成功
if (ret.code === TPE_OK) {
window.location.href = ywl.page_options.ref;
}
else {
} else {
hide_op_box();
show_op_box('error', '无法登录TELEPORT' + ret.message);
console.log(ret);
@ -137,31 +133,6 @@ ywl.create_app = function () {
$('#btn_login').removeAttr('disabled');
}
);
// $.ajax({
// type: 'GET',
// url: '/auth/verify-user',
// jsonp: "callback",
// data: {username: username, userpwd: userpwd, captcha: captcha},
// dataType: 'jsonp',
// success: function (data) {
// if (data.code == 0) {
// // 验证成功
// window.location.href = ywl.page_options.ref;
// }
// else {
// hide_op_box();
// show_op_box('error', '无法登录TELEPORT');
// }
//
// $('#btn_login').removeAttr('disabled');
// },
// error: function () {
// hide_op_box();
// show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
// $('#btn_login').removeAttr('disabled');
// }
// });
};
return _app;

View File

@ -1,7 +1,7 @@
/**
* Created by mi on 2016/7/4.
*/
"use strict";
var g_cert_dlg_info = null;
ywl.on_init = function (cb_stack, cb_args) {
var dom_id = '#ywl_cert_list';
@ -71,7 +71,7 @@ ywl.on_init = function (cb_stack, cb_args) {
ywl.on_host_table_created = function (tbl) {
tbl.on_cell_created = function (row_id, col_key, cell_obj) {
if (col_key == 'action') {
if (col_key === 'action') {
var row_data = tbl.get_row(row_id);
//console.log('row_data', row_data);
$(cell_obj).find('[ywl-btn-edit]').click(function () {
@ -82,18 +82,18 @@ ywl.on_host_table_created = function (tbl) {
var _fn_sure = function (cb_stack, cb_args) {
ywl.ajax_post_json('/host/delete-cert', {cert_id: cert_id},
function (ret) {
if (ret.code == 0) {
if (ret.code === TPE_OK) {
tbl.remove_row(row_id);
ywl.notify_success('删除成功!');
} else if (ret.code == -2) {
} else if (ret.code === -2) {
ywl.notify_error('不能删除,有主机使用了此密钥!');
} else {
ywl.notify_error('删除失败!');
ywl.notify_error('删除失败!错误代码:'+ret.code);
}
},
function (ret) {
ywl.notify_error('删除失败');
function () {
ywl.notify_error('网络通讯失败!');
}
);
};
@ -189,7 +189,7 @@ ywl.create_cert_info_dlg = function (tbl) {
ywl.notify_error('必须填写公钥内容!');
return false;
}
if (cert_info_dlg.update == 0 && cert_info_dlg.cert_pri.length == 0) {
if (cert_info_dlg.update === 0 && cert_info_dlg.cert_pri.length === 0) {
ywl.notify_error('添加密钥时,必须填写私钥内容!');
return false;
}
@ -197,7 +197,7 @@ ywl.create_cert_info_dlg = function (tbl) {
};
cert_info_dlg.post = function () {
if (cert_info_dlg.update == 1) {
if (cert_info_dlg.update === 1) {
ywl.ajax_post_json('/host/update-cert', {cert_id: cert_info_dlg.cert_id, cert_name: cert_info_dlg.cert_name, cert_pub: cert_info_dlg.cert_pub, cert_pri: cert_info_dlg.cert_pri},
function (ret) {
var update_args = {cert_id: cert_info_dlg.cert_id, cert_name: cert_info_dlg.cert_name};
@ -205,19 +205,19 @@ ywl.create_cert_info_dlg = function (tbl) {
ywl.notify_success('密钥更新成功!');
cert_info_dlg.hide();
},
function (ret) {
function () {
ywl.notify_error('密钥更新失败!');
}
);
} else {
ywl.ajax_post_json('/host/add-cert', {cert_name: cert_info_dlg.cert_name, cert_pub: cert_info_dlg.cert_pub, cert_pri: cert_info_dlg.cert_pri},
function (ret) {
if(ret.code == 0){
if(ret.code === TPE_OK){
cert_info_dlg.tbl.reload();
ywl.notify_success('密钥添加成功!');
cert_info_dlg.hide();
}else if(ret.code == -2){
ywl.notify_error('错误,没有启动核心服务!');
}else if(ret.code === TPE_NO_CORE_SERVER){
ywl.notify_error('错误没有启动核心服务!');
}else{
ywl.notify_error('密钥添加失败code:' + ret.code);
}

View File

@ -68,9 +68,9 @@ function get_system_group_by_id(gid) {
}
function get_command_name_by_id(cmd_id) {
return ywl.assist.get_cache_by_id(CACHE_TYPE_COMMAND, cmd_id);
}
//function get_command_name_by_id(cmd_id) {
// return ywl.assist.get_cache_by_id(CACHE_TYPE_COMMAND, cmd_id);
//}
//function notify_error(message_, title_) {
// var _title = title_ || '';

View File

@ -1,13 +1,13 @@
"use strict";
var OS_TYPE_WINDOWS = 1;
var OS_TYPE_LINUX = 2;
var PROTOCOL_TYPE_RDP = 1;
var PROTOCOL_TYPE_SSH = 2;
var PROTOCOL_TYPE_TELNET = 3;
var AUTH_TYPE_PASSWORD = 1;
var AUTH_TYPE_SSHKEY = 2;
var AUTH_NONE = 0;
//var OS_TYPE_WINDOWS = 1;
//var OS_TYPE_LINUX = 2;
//var PROTOCOL_TYPE_RDP = 1;
//var PROTOCOL_TYPE_SSH = 2;
//var PROTOCOL_TYPE_TELNET = 3;
//var AUTH_TYPE_PASSWORD = 1;
//var AUTH_TYPE_SSHKEY = 2;
//var AUTH_NONE = 0;
var g_assist = null;

View File

@ -1003,20 +1003,20 @@ ywl.create_table_render = function (tbl, on_created) {
return ret;
};
_tbl_render.host_status = function (row_id, fields) {
if (fields.status == HOST_STAT_ACTIVE) {
switch (fields.online) {
case AGENT_STAT_ONLINE:
return '<span class="badge badge-success">在线</span>';
case AGENT_STAT_OFFLINE:
return '<span class="badge badge-danger">离线</span>';
default:
return '<span class="badge badge-warning">未知</span>';
}
} else {
return '<span class="badge badge-ignore">- 未使用 -</span>';
}
};
// _tbl_render.host_status = function (row_id, fields) {
// if (fields.status == HOST_STAT_ACTIVE) {
// switch (fields.online) {
// case AGENT_STAT_ONLINE:
// return '<span class="badge badge-success">在线</span>';
// case AGENT_STAT_OFFLINE:
// return '<span class="badge badge-danger">离线</span>';
// default:
// return '<span class="badge badge-warning">未知</span>';
// }
// } else {
// return '<span class="badge badge-ignore">- 未使用 -</span>';
// }
// };
_tbl_render.sys_type = function (row_id, fields) {
switch (fields.sys_type) {

View File

@ -41,7 +41,7 @@ var speed_offset = 0;
ywl.req_record_info = function (record_id, file_id, repeat) {
ywl.ajax_post_json_time_out('/log/get-record-file-info', {id: record_id, file_id: file_id}, 30 * 1000,
function (ret) {
if (ret.code == 0) {
if (ret.code === TPE_OK) {
g_data[file_id] = ret.data;
if ((g_down_play_file_id + 1) <= g_total_file_count) {
@ -49,9 +49,7 @@ ywl.req_record_info = function (record_id, file_id, repeat) {
ywl.req_record_info(record_id, g_down_play_file_id, true);
g_down_play_file_id++;
}
}
//console.log('req_record_info successful');
} else {
console.log('req_record_info error ', ret.code);
}
@ -77,11 +75,13 @@ ywl.on_init = function (cb_stack, cb_args) {
ywl.ajax_post_json('/log/get-record-header', {id: record_id},
function (ret) {
if (ret.code == 0) {
if (ret.code === TPE_OK) {
g_header = ret.data.header;
g_total_file_count = g_header.file_count;
g_total_time = g_header.time_used;
$('#recorder-info').html(g_header.account + ' 于 ' + format_datetime(g_header.start) + ' 访问 ' + g_header.user_name + '@' + g_header.ip + ':' + g_header.port);
// 请求第一个录像数据块
g_down_play_file_id = 0;
ywl.req_record_info(record_id, g_down_play_file_id, true);

View File

@ -7,19 +7,18 @@ var g_current_version = "";
var g_host_name = window.location.hostname;
var error_process = function (ret, func_success, func_error) {
// console.log("ret", ret);
var code = ret.code;
if (code == TPE_OK) {
if (code === TPE_OK) {
func_success(ret);
return;
}
if (code == TPE_START_CLIENT) {
if (code === TPE_START_CLIENT) {
func_error(TPE_START_CLIENT, '启动本地客户端进程失败,请检查命令行是否正确:' + ret.path);
console.log('启动本地进程失败,命令行:', ret.path);
} else if (code == TPE_JSON_FORMAT || code == TPE_PARAM) {
} else if (code === TPE_JSON_FORMAT || code === TPE_PARAM) {
func_error(TPE_START_CLIENT, "启动本地客户端进程失败:启动参数错误!");
} else if (code == TPE_OLD_ASSIST) {
} else if (code === TPE_OLD_ASSIST) {
func_error(TPE_OLD_ASSIST, '助手版本太低,请下载最新版本!');
}
else {
@ -47,7 +46,7 @@ var teleport_init = function (last_version, req_version, func_success, func_erro
func_error(ret, TPE_OLD_ASSIST, '助手版本太低,请<a style="color:#aaaaff;" target="_blank" href="http://teleport.eomsoft.net/download">下载最新版本</a>');
}
},
error: function (jqXhr) {
error: function () {
func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手可能尚未启动');
}
});
@ -60,7 +59,6 @@ var version_compare = function () {
};
var to_teleport = function (url, args, func_success, func_error) {
var auth_id = args['auth_id'];
// 开始Ajax调用
var args_ = JSON.stringify({auth_id: auth_id});
@ -94,7 +92,7 @@ var to_teleport = function (url, args, func_success, func_error) {
success: function (ret) {
error_process(ret, func_success, func_error);
},
error: function (jqXhr) {
error: function () {
func_error(TPE_NO_ASSIST, '无法连接到teleport助手可能尚未启动');
}
});
@ -109,7 +107,6 @@ var to_teleport = function (url, args, func_success, func_error) {
};
var to_admin_teleport = function (url, args, func_success, func_error) {
var host_auth_id = args['host_auth_id'];
// 开始Ajax调用
var args_ = JSON.stringify({host_auth_id: host_auth_id});
@ -124,7 +121,7 @@ var to_admin_teleport = function (url, args, func_success, func_error) {
if (ret.code === 0) {
var session_id = ret.data.session_id;
var data = {
server_ip: g_host_name, // args.server_ip,
server_ip: g_host_name,
server_port: parseInt(args.server_port),
host_ip: args.host_ip,
size: parseInt(args.size),
@ -158,7 +155,6 @@ var to_admin_teleport = function (url, args, func_success, func_error) {
};
var to_admin_fast_teleport = function (url, args, func_success, func_error) {
// 开始Ajax调用
var args_ = JSON.stringify(args);
$.ajax({
@ -172,7 +168,7 @@ var to_admin_fast_teleport = function (url, args, func_success, func_error) {
if (ret.code === 0) {
var session_id = ret.data.session_id;
var data = {
server_ip: g_host_name, //args.server_ip,
server_ip: g_host_name,
server_port: parseInt(args.server_port),
host_ip: args.host_ip,
size: parseInt(args.size),
@ -210,7 +206,6 @@ var to_admin_fast_teleport = function (url, args, func_success, func_error) {
};
var start_rdp_replay = function (args, func_success, func_error) {
var args_ = encodeURIComponent(JSON.stringify(args));
$.ajax({
type: 'GET',
@ -227,7 +222,7 @@ var start_rdp_replay = function (args, func_success, func_error) {
console.log('ret', ret);
},
error: function () {
func_error(TPE_NETWORK, '远程网络通讯失败!');
func_error(TPE_NETWORK, '与助手的络通讯失败!');
}
});
};

View File

@ -1,12 +1,23 @@
"use strict";
var USER_TYPE_TEAM_MEMBER = 1;
var USER_TYPE_TEAM_LEADER = 9;
var USER_TYPE_SYS_ADMIN = 99;
var PROTOCOL_TYPE_RDP = 1;
var PROTOCOL_TYPE_SSH = 2;
var PROTOCOL_TYPE_TELNET = 3;
var AGENT_STAT_ONLINE = 1;
var AGENT_STAT_OFFLINE = 0;
// var AGENT_STAT_NOT_ACTIVE = 2;
var OS_TYPE_WINDOWS = 1;
var OS_TYPE_LINUX = 2;
var AUTH_TYPE_PASSWORD = 1;
var AUTH_TYPE_SSHKEY = 2;
var AUTH_NONE = 0;
//var USER_TYPE_TEAM_MEMBER = 1;
//var USER_TYPE_TEAM_LEADER = 9;
//var USER_TYPE_SYS_ADMIN = 99;
//var AGENT_STAT_ONLINE = 1;
//var AGENT_STAT_OFFLINE = 0;
//var AGENT_STAT_NOT_ACTIVE = 2;
var HOST_STAT_NOT_ACTIVE = 0;
var HOST_STAT_ACTIVE = 2;
@ -87,6 +98,7 @@ var TPE_DATA = 127; // 数据错误
// #define TPE_OPENFILE_ERROR 0x1007 // 无法打开文件
// #define TPE_GETTEMPPATH_ERROR 0x1007
var TPE_OPENFILE = 300; // 无法打开文件
//-------------------------------------------------------
@ -103,4 +115,52 @@ var TPE_START_CLIENT = 100002; // 无法启动客户端程序(无法创建进
var TPE_NO_CORE_SERVER = 200000; // 未能检测到核心服务
function tp_error_msg(error_code) {
switch (error_code) {
case TPE_FAILED:
return '内部错误';
case TPE_NETWORK:
return '网络错误';
//-------------------------------------------------------
// HTTP请求相关错误
//-------------------------------------------------------
case TPE_HTTP_METHOD:
return '无效/错误的请求方法';
case TPE_HTTP_URL_ENCODE:
return 'URL编码错误无法解码';
case TPE_UNKNOWN_CMD:
return '未知命令';
case TPE_JSON_FORMAT:
return '错误的JSON格式数据';
case TPE_PARAM:
return '参数错误';
case TPE_DATA:
return '数据错误';
case TPE_OPENFILE:
return '无法打开文件';
//-------------------------------------------------------
// 助手程序专用错误值
//-------------------------------------------------------
case TPE_NO_ASSIST:
return '未能检测到助手程序';
case TPE_OLD_ASSIST:
return '助手程序版本太低';
case TPE_START_CLIENT:
return '无法启动客户端程序(无法创建进程)';
//-------------------------------------------------------
// 核心服务专用错误值
//-------------------------------------------------------
case TPE_NO_CORE_SERVER:
return '未能检测到核心服务';
default:
return '未知错误';
}
}

View File

@ -128,6 +128,12 @@ body {
background: url(../img/login/side-001.jpg) 0 0 no-repeat;
}
@media screen and (max-width: 990px) {
#leftside {
display: none;
}
}
#leftside h1 {
font-size: 24px;
color: #888;

View File

@ -55,7 +55,7 @@
<div id="foot">
<nav class="navbar navbar-default navbar-fixed-bottom">
<div class="container">
<p>触维软件旗下产品 | TELEPORT v${eom_ver.TS_VER} | &copy;2015 - 2016 <a href="http://www.eomsoft.net/" target="_blank">触维软件</a>,保留所有权利。</p>
<p>触维软件旗下产品 | TELEPORT v${eom_ver.TS_VER} | &copy;2015 - 2017 <a href="http://www.eomsoft.net/" target="_blank">触维软件</a>,保留所有权利。</p>
</div>
</nav>
</div>

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-key fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -52,27 +52,28 @@
'name': '日志查询',
'icon': 'fa-database',
},
## {
## 'require_type': 1,
## 'id': 'pwd',
## 'link': '/pwd',
## 'name': '密码修改',
## 'icon': 'fa-pencil-square-o',
## },
## {
## 'require_type': 1,
## 'id': 'exit',
## 'link': '/exit',
## 'name': '安全退出',
## 'icon': 'fa-sign-out',
## },
{
'separator': true,
'require_type': 1,
'id': 'assist-config',
'link': 'http://127.0.0.1:50022/config',
'target': '_blank',
'name': '助手配置',
'icon': 'fa-pencil-square-o',
},
{
'require_type': 1,
'id': 'pwd',
'link': '/pwd',
'name': '密码修改',
'icon': 'fa-pencil-square-o',
},
{
'require_type': 1,
'id': 'exit',
'link': '/exit',
'name': '安全退出',
'icon': 'fa-sign-out',
'icon': 'fa-cog',
},
]
%>
@ -103,7 +104,8 @@
<i class="fa fa-caret-right"></i></span>
</a>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="/auth/logout" id="btn-logout">退出</a></li>
<li><a href="/pwd" id="btn-logout">修改密码</a></li>
<li><a href="/auth/logout" id="btn-logout">安全退出</a></li>
</ul>
</div>
@ -119,6 +121,10 @@
%for menu in _sidebar:
%if menu['require_type'] <= current_user['type']:
%if 'separator' in menu:
<hr style="border:none;border-bottom:1px solid #636363;margin-bottom:0;margin-top:5px;"/>
%endif
%if 'sub' in menu and len(menu['sub']) > 0:
<li id="sidebar_menu_${menu['id']}"><a href="javascript:;"
onclick="ywl._sidebar_toggle_submenu('${menu['id']}');"><i
@ -150,7 +156,7 @@
<hr style="border:none;border-bottom:1px dotted #4a4a4a;margin-bottom:0;"/>
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:100px;text-align: right">服务端:</span><span class="mono">v${eom_ver.TS_VER}</span></div>
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:100px;text-align: right">助手:</span><span class="mono" id="tp-assist-version" req-version=${eom_ver.TP_ASSIST_REQUIRE}>v${eom_ver.TP_ASSIST_LAST_VER}</span></div>
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:100px;text-align: right">当前助手:</span><span class="mono">v${eom_ver.TP_ASSIST_REQUIRE}</span></div>
<hr style="border:none;border-bottom:1px dotted #4a4a4a;margin-bottom:0;margin-top:5px;"/>
</div>
<!-- end sidebar scrollbar -->

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-object-group fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -155,8 +155,8 @@
<label class="col-sm-3 control-label" for="auth-sys-type"><strong>操作系统:</strong></label>
<div class="col-sm-6">
<select id="auth-sys-type" class="form-control">
<option value="2">Linux</option>
<option value="1">Windows</option>
<option value=2>Linux</option>
<option value=1>Windows</option>
</select>
</div>
</div>
@ -173,7 +173,6 @@
</div>
</div>
<div class="form-group form-group-sm">
<label class="col-sm-3 control-label" for="dlg-edit-host-group"><strong>主机分组:</strong></label>
<div class="col-sm-6">
@ -200,110 +199,18 @@
</div>
</div>
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label"><strong>远程访问协议:</strong></label>
## <div class="col-sm-9">
##
## <div class="dlg-protocol-group">
## <ul>
## <li class="item-name"><label><input id="dlg-edit-host-allow-ssh" type="checkbox"> SSH</label></li>
## <li>端口号</li>
## <li class="item-input"><input id="dlg-edit-host-ssh-port" type="text" class="form-control" placeholder="默认端口 22" value="22"></li>
## </ul>
## </div>
##
## <div class="dlg-protocol-group">
## <ul>
## <li class="item-name"><label><input type="checkbox" id="dlg-edit-host-allow-rdp"> RDP</label></li>
## <li>端口号</li>
## <li class="item-input"><input id="dlg-edit-host-rdp-port" type="text" class="form-control" placeholder="默认端口 3389" value="3389"></li>
## </ul>
## </div>
##
## <div class="dlg-protocol-group">
## <ul>
## <li class="item-name"><label><input type="checkbox" id="dlg-edit-host-allow-telnet"> TELNET</label></li>
## <li>端口号</li>
## <li class="item-input"><input id="dlg-edit-host-telnet-port" type="text" class="form-control" placeholder="默认端口 23" value="23"></li>
## </ul>
## </div>
## </div>
## </div>
<hr class="small"/>
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-protocol-type"><strong>远程访问协议:</strong></label>
## <div class="col-sm-6">
## <select id="auth-protocol-type" class="form-control">
## <option value="2">SSH</option>
## <option value="1">RDP (远程桌面协议)</option>
## </select>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label for="auth-host-port" class="col-sm-3 control-label"><strong>远程主机端口:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-port" type="text" class="form-control" value="22"/>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-auth-type"><strong>认证方式:</strong></label>
## <div class="col-sm-6">
## <select id="auth-auth-type" class="form-control">
## <option value="1">用户名/密码</option>
## <option value="2">SSH密钥</option>
## </select>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label for="auth-host-username" class="col-sm-3 control-label"><strong>用户名:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-username" type="text" class="form-control" value=""/>
## </div>
## </div>
##
## <div id="auth-block-pswd">
## <div class="form-group form-group-sm">
## <label for="auth-host-pswd" class="col-sm-3 control-label"><strong>密码:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-pswd" type="password" class="form-control" placeholder="不填写则使用已存储的密码"/>
## </div>
## </div>
## <div class="form-group form-group-sm">
## <label for="auth-host-pswd-confirm" class="col-sm-3 control-label"><strong>确认密码:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-pswd-confirm" type="password" class="form-control" placeholder="请再次输入密码"/>
## </div>
## </div>
## </div>
##
##
## <div id="auth-block-sshkey" style="display: none;">
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-sshkey-list"><strong>SSH密钥</strong></label>
## <div class="col-sm-6">
## <select id="auth-sshkey-list" class="form-control"></select>
## </div>
## </div>
## </div>
</div>
</div>
<div class="modal-footer">
## <button type="button" class="btn btn-sm btn-success" id="test-btn-connect"><i class="fa fa-check fa-fw"></i> 测试连接</button>
<button type="button" class="btn btn-sm btn-primary" id="host-btn-save"><i class="fa fa-check fa-fw"></i> 保存主机信息</button>
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 取消</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dialog-host-user-edit" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
@ -314,133 +221,18 @@
<div class="form-horizontal">
<div class="form-group form-group">
<label class="col-sm-2 control-label" for="auth-protocol-type"><strong>登录账号:</strong></label>
<div class="col-sm-10" id="sys-user-list">
## <div class="remote-action-group">
## <ul>
## <li class="remote-action-name"></li>
## <li class="remote-action-protocol">Telnet</li>
## <li class="remote-action-noauth">无需认证</li>
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-primary disabled" disabled data-action="remote" data-sub-protocol="1"><i class="fa fa-edit fa-fw"></i> 修改</button>
## </li>
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-danger" data-action="remote" data-sub-protocol="2"><i class="fa fa-trash-o fa-fw"></i> 删除</button>
## </li>
## </ul>
## </div>
## <div class="remote-action-group">
## <ul>
## <li class="remote-action-name">root</li>
## <li class="remote-action-protocol">SSH</li>
## <li class="remote-action-sshkey">私钥认证</li>
## ## <li class="remote-action-btn"><button type="button" class="btn btn-sm btn-success" data-action="remote" data-sub-protocol="1"><i class="fa fa-flash fa-fw"></i> 测试</button></li>
##
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-edit fa-fw"></i> 修改</button>
## </li>
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-danger" data-action="remote" data-sub-protocol="2"><i class="fa fa-trash-o fa-fw"></i> 删除</button>
## </li>
## </ul>
## </div>
## <div class="remote-action-group">
## <ul>
## <li class="remote-action-name">tester</li>
## <li class="remote-action-protocol">SSH</li>
## <li class="remote-action-password">密码认证</li>
## ## <li class="remote-action-btn"><button type="button" class="btn btn-sm btn-success" data-action="remote" data-sub-protocol="1"><i class="fa fa-flash fa-fw"></i> 测试</button></li>
##
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-edit fa-fw"></i> 修改</button>
## </li>
## <li class="remote-action-btn">
## <button type="button" class="btn btn-sm btn-danger" data-action="remote" data-sub-protocol="2"><i class="fa fa-trash-o fa-fw"></i> 删除</button>
## </li>
## </ul>
## </div>
## <button type="button" class="btn btn-sm btn-primary" id="btn-add-user"><i class="fa fa-plus fa-fw"></i> 添加登录账号</button>
</div>
<div class="col-sm-10" id="sys-user-list"></div>
</div>
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-protocol-type"><strong>远程访问协议:</strong></label>
## <div class="col-sm-6">
## <select id="auth-protocol-type" class="form-control">
## <option value="2">SSH</option>
## <option value="1">RDP (远程桌面协议)</option>
## </select>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label for="auth-host-port" class="col-sm-3 control-label"><strong>远程主机端口:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-port" type="text" class="form-control" value="22"/>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-auth-type"><strong>认证方式:</strong></label>
## <div class="col-sm-6">
## <select id="auth-auth-type" class="form-control">
## <option value="1">用户名/密码</option>
## <option value="2">SSH密钥</option>
## </select>
## </div>
## </div>
##
## <div class="form-group form-group-sm">
## <label for="auth-host-username" class="col-sm-3 control-label"><strong>用户名:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-username" type="text" class="form-control" value=""/>
## </div>
## </div>
##
## <div id="auth-block-pswd">
## <div class="form-group form-group-sm">
## <label for="auth-host-pswd" class="col-sm-3 control-label"><strong>密码:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-pswd" type="password" class="form-control" placeholder="不填写则使用已存储的密码"/>
## </div>
## </div>
## <div class="form-group form-group-sm">
## <label for="auth-host-pswd-confirm" class="col-sm-3 control-label"><strong>确认密码:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-pswd-confirm" type="password" class="form-control" placeholder="请再次输入密码"/>
## </div>
## </div>
## </div>
##
##
## <div id="auth-block-sshkey" style="display: none;">
## <div class="form-group form-group-sm">
## <label class="col-sm-3 control-label" for="auth-sshkey-list"><strong>SSH密钥</strong></label>
## <div class="col-sm-6">
## <select id="auth-sshkey-list" class="form-control"></select>
## </div>
## </div>
## </div>
</div>
</div>
<div class="modal-footer">
## <button type="button" class="btn btn-sm btn-success" id="test-btn-connect"><i class="fa fa-check fa-fw"></i> 测试连接</button>
<button type="button" class="btn btn-sm btn-primary" id="host-user-btn-save"><i class="fa fa-check fa-fw"></i> 确定</button>
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 取消</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dialog_user" tabindex="-1" role="dialog">
<div class="modal-dialog" style="width:460px;top:80px;">
<div class="modal-content">
@ -464,13 +256,6 @@
</div>
</div>
## <div class="form-group form-group-sm">
## <label for="auth-host-port" class="col-sm-3 control-label"><strong>远程主机端口:</strong></label>
## <div class="col-sm-6">
## <input id="auth-host-port" type="text" class="form-control" value="22"/>
## </div>
## </div>
<div class="form-group form-group-sm">
<label class="col-sm-4 control-label" for="auth-user-type"><strong>认证方式:</strong></label>
<div class="col-sm-6" id="auth-sys-user-type-combox">
@ -530,9 +315,7 @@
</div>
</div>
</div>
</div>
<div class="modal-footer">
@ -594,18 +377,8 @@
</%block>
<%block name="embed_js">
<script type="text/javascript">
## ywl.add_page_options({
## group_list: ${group_list},
## cert_list: ${cert_list},
## ts_server: ${ts_server}
## });
##
## $(document).ready(function () {
## });
ywl.add_page_options(${page_param});
</script>
</%block>

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-database fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -11,6 +11,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server"></i> ${self.attr.page_title_}</li>
<li><span id="recorder-info"></span></li>
</ol>
</%block>

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-pencil-square-o fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-cogs fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -12,7 +12,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
<li><i class="fa fa-user fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>

View File

@ -14,6 +14,6 @@ Build 构建号。构建号用于表明此版本发布之前进行了多少
TELEPORT_SERVER 2.1.2.1
TELEPORT_ASSIST 2.1.2.1
TELEPORT_SERVER 2.2.5.1
TELEPORT_ASSIST 2.2.5.1
TELEPORT_ASSIST_REQUIRE 2.0.0.1