Merge branch 'dev' of github.com:eomsoft/teleport into dev

# Conflicts:
#	server/www/teleport/app/eom_app/module/record.py
pull/32/merge
Apex Liu 2017-03-08 14:27:44 +08:00
commit 86af784330
24 changed files with 691 additions and 1112 deletions

View File

@ -48,13 +48,6 @@ class WebServerCore:
if not cfg.load_web(_cfg_file):
return False
# TODO: 不要直接读取core.ini而是通过core的json-rpc获取其配置数据
# _cfg_file = os.path.join(cfg.cfg_path, 'core.ini')
# if not cfg.load_core(_cfg_file):
# return False
# if not self._get_core_server_config():
# return False
cfg.log_path = os.path.abspath(options['log_path'])
cfg.log_file = os.path.join(cfg.log_path, 'tpweb.log')

View File

@ -28,7 +28,6 @@ __all__ = ['async_post_http', 'async_enc']
@tornado.gen.coroutine
def async_post_http(post_data):
print('async_post_http:', post_data)
try:
v = json.dumps(post_data)
data = urllib.parse.quote(v).encode('utf-8')
@ -36,7 +35,7 @@ def async_post_http(post_data):
c = tornado.httpclient.AsyncHTTPClient()
r = yield c.fetch(cfg.core_server_rpc, body=data, method='POST')
print('async_post_http return:', r.body.decode())
# print('async_post_http return:', r.body.decode())
return json.loads(r.body.decode())
except:
return None

View File

@ -79,7 +79,7 @@ controllers = [
(r'/host/add-host', host.AddHost),
(r'/host/lock-host', host.LockHost),
(r'/host/delete-host', host.DeleteHost),
(r'/host/export-host', host.ExportHost),
(r'/host/export-host', host.ExportHostHandler),
(r'/host/get-cert-list', host.GetCertList),
(r'/host/add-cert', host.AddCert),
(r'/host/delete-cert', host.DeleteCert),
@ -92,7 +92,7 @@ controllers = [
# (r'/host/get-host-extend-info', host.GetHostExtendInfo),
# (r'/host/update-host-extend-info', host.UpdateHostExtendInfo),
(r'/host/update', host.UpdateHandler),
(r'/host/load-file', host.LoadFile),
(r'/host/upload-import', host.UploadAndImportHandler),
(r'/host/', host.IndexHandler),
(r'/host', host.IndexHandler),
(r'/host/get-session-id', host.GetSessionId),

View File

@ -16,13 +16,11 @@ class LoginHandler(SwxAppHandler):
else:
user_name = _user['name']
page_param = {
param = {
'ref': self.get_argument('ref', '/'),
'login_type': 'account',
'user_name': user_name
}
page_param = json.dumps(page_param)
self.render('auth/login.mako', page_param=page_param)
self.render('auth/login.mako', page_param=json.dumps(param))
class VerifyUser(SwxJsonpHandler):
@ -70,7 +68,6 @@ class VerifyUser(SwxJsonpHandler):
_user['type'] = account_type
self.set_session('user', _user)
# log.v('set session ok.\n')
return self.write_jsonp(0)
except:
@ -116,14 +113,10 @@ class VerifyCaptchaHandler(SwxJsonpHandler):
class ModifyPwd(SwxAuthJsonHandler):
def post(self):
# print('verify-ticket')
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
_old_pwd = args['o_pwd']

View File

@ -11,10 +11,9 @@ import tornado.httpclient
from eom_app.app.configs import app_cfg
from eom_app.app.util import *
from eom_app.module import host
# from eom_app.module.common import *
from eom_common.eomcore.logger import *
from eom_app.app.session import web_session
from .base import SwxAuthHandler, SwxAuthJsonHandler, SwxAdminJsonHandler
from .base import SwxAuthHandler, SwxAdminHandler, SwxAuthJsonHandler, SwxAdminJsonHandler
cfg = app_cfg()
@ -29,53 +28,24 @@ class IndexHandler(SwxAuthHandler):
if _user is None:
return self.write(-1)
# static_path = cfg.static_path
# var_js = os.path.join(static_path, 'js', 'var.js')
try:
# f = open(var_js, 'w')
_type = _user['type']
# config_list = set.get_config_list()
ts_server = dict()
# ts_server['ip'] = config_list['ts_server_ip']
# ts_server['ip'] = cfg['ts_server_ip']
# ts_server['ip'] = '0.0.0.0'
param = dict()
# ts_server['ssh_port'] = config_list['ts_server_ssh_port']
# ts_server['rdp_port'] = config_list['ts_server_rdp_port']
# ts_server['telnet_port'] = config_list['ts_server_telnet_port']
param['core'] = {
'ssh_port': cfg.core.ssh.port,
'rdp_port': cfg.core.telnet.port,
'telnet_port': cfg.core.telnet.port
}
ts_server['ssh_port'] = cfg.core.ssh.port
ts_server['rdp_port'] = cfg.core.rdp.port
ts_server['telnet_port'] = cfg.core.telnet.port
param['group_list'] = host.get_group_list()
# f.write("\"use strict\";\nvar teleport_ip = \"{}\";\n".format(ts_server['ip']))
except Exception:
return self.write(-1)
# finally:
# f.close()
if _type >= 100:
group_list = host.get_group_list()
cert_list = host.get_cert_list()
self.render('host/admin_index.mako',
group_list=group_list,
cert_list=cert_list,
ts_server=ts_server)
if _user['type'] >= 100:
param['cert_list'] = host.get_cert_list()
self.render('host/admin_index.mako', page_param=json.dumps(param))
else:
group_list = host.get_group_list()
# if config_list is None:
# return
self.render('host/common_index.mako',
group_list=group_list,
ts_server=ts_server)
self.render('host/common_index.mako', page_param=json.dumps(param))
class LoadFile(SwxAuthJsonHandler):
# def get(self):
# pass
class UploadAndImportHandler(SwxAdminJsonHandler):
# TODO: 导入操作可能会比较耗时,应该分离导入和获取导入状态两个过程,在页面上可以呈现导入进度,并列出导出成功/失败的项
@tornado.gen.coroutine
@ -96,7 +66,8 @@ class LoadFile(SwxAuthJsonHandler):
csv_filename = ''
try:
upload_path = os.path.join(os.path.dirname(__file__), 'csv-files') # 文件的暂存路径
# upload_path = os.path.join(os.path.dirname(__file__), 'csv-files') # 文件的暂存路径
upload_path = os.path.join(cfg.data_path, 'tmp') # 文件的暂存路径
if not os.path.exists(upload_path):
os.mkdir(upload_path)
file_metas = self.request.files['csvfile'] # 提取表单中namefile的文件元数据
@ -411,49 +382,26 @@ class DeleteHost(SwxAuthJsonHandler):
return
class ExportHost(SwxAuthJsonHandler):
def post(self):
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
class ExportHostHandler(SwxAdminHandler):
def get(self):
self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=teleport-host-export.csv')
order = dict()
order['name'] = 'host_id'
order['asc'] = True
limit = dict()
limit['page_index'] = 0
limit['per_page'] = 999999
_total, _hosts = host.get_all_host_info_list(dict(), order, limit, True)
export_file = os.path.join(cfg.static_path, 'download', 'export_csv_data.csv')
if os.path.exists(export_file):
os.remove(export_file)
try:
csv_file = open(export_file, 'w', encoding='utf8')
# with open(export_file, 'wb') as csvfile:
# spamwriter = csv.writer(csvfile)
# spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
# spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
csv_header = "分组ID, 操作系统, " \
"IP地址, 端口, 协议, 状态, 描述, " \
"系统用户, 系统密码, 是否加密,附加参数, 密钥ID, 认证类型"
csv_file.write(csv_header)
csv_file.write('\n')
except:
log.e('')
csv_file.close()
self.write_json(-1)
return
self.write("分组ID, 操作系统, IP地址, 端口, 协议, 状态, 描述, 系统用户, 系统密码, 是否加密, 附加参数, 密钥ID, 认证类型\n".encode('gbk'))
try:
for h in _hosts:
auth_list = h['auth_list']
# 分组ID, 操作系统, IP地址, 端口, 协议, 状态, 描述, 系统用户, 系统密码, 是否加密,附加参数, , 密钥ID, 认证类型
# 分组ID, 操作系统, IP地址, 端口, 协议, 状态, 描述, 系统用户, 系统密码, 是否加密,附加参数, 密钥ID, 认证类型
for j in auth_list:
row_string = ''
# row_string = str(h['host_id'])
@ -489,46 +437,30 @@ class ExportHost(SwxAuthJsonHandler):
row_string += str(j['cert_id'])
row_string += ','
row_string += str(j['auth_mode'])
csv_file.write(row_string)
csv_file.write('\n')
# row = list()
# row.append(h['host_id'])
# row.append(h['group_id'])
# row.append(h['host_sys_type'])
# row.append(h['host_ip'])
# row.append(h['host_port'])
# row.append(h['protocol'])
# row.append(h['host_lock'])
# row.append(h['host_desc'])
# auth_list = h['auth_list']
# row.append(j['host_auth_id'])
# row.append(j['user_name'])
# row.append(j['user_pswd'])
# row.append(1)
# row.append(j['user_param'])
# row.append(j['cert_id'])
# row.append(j['auth_mode'])
except Exception as e:
self.write(row_string.encode('gbk'))
self.write('\n')
except IndexError:
self.write('**********************************************\n'.encode('gbk'))
self.write('!!错误!!\n'.encode('gbk'))
self.write('导出过程中发生了错误!!\n'.encode('gbk'))
self.write('**********************************************\n'.encode('gbk'))
log.e('')
finally:
csv_file.close()
url = '/static/download/export_csv_data.csv'
ret = dict()
ret['url'] = url
self.write_json(0, data=ret)
return
self.finish()
class GetCertList(SwxAuthJsonHandler):
def post(self):
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
# 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
_certs = host.get_cert_list()
if _certs is None:
self.write_json(-1)
@ -539,7 +471,6 @@ class GetCertList(SwxAuthJsonHandler):
class AddCert(SwxAuthJsonHandler):
@tornado.gen.coroutine
def post(self):
args = self.get_argument('args', None)
@ -557,7 +488,6 @@ class AddCert(SwxAuthJsonHandler):
self.write_json(-1)
return
# ret_code, cert_pri =
_yr = async_enc(cert_pri)
return_data = yield _yr
if return_data is None:
@ -568,16 +498,6 @@ class AddCert(SwxAuthJsonHandler):
cert_pri = return_data['data']
# try:
# ret_code, cert_pri = get_enc_data(cert_pri)
# except Exception as e:
# self.write_json(-100)
# return
# if 0 != ret_code:
# self.write_json(ret_code)
# return
try:
ret = host.add_cert(cert_pub, cert_pri, cert_name)
if ret:
@ -612,7 +532,6 @@ class DeleteCert(SwxAuthJsonHandler):
class UpdateCert(SwxAuthJsonHandler):
@tornado.gen.coroutine
def post(self):
args = self.get_argument('args', None)
@ -638,13 +557,6 @@ class UpdateCert(SwxAuthJsonHandler):
return self.write_json(-1)
cert_pri = return_data['data']
#
# try:
# ret_code, cert_pri = get_enc_data(cert_pri)
# except Exception as e:
# return self.write_json(-100)
# if 0 != ret_code:
# return self.write_json(ret_code)
try:
ret = host.update_cert(cert_id, cert_pub, cert_pri, cert_name)
@ -752,64 +664,6 @@ class AddHostToGroup(SwxAuthJsonHandler):
return
# class GetHostExtendInfo(SwxAuthJsonHandler):
# def post(self):
# 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
# try:
# host_id = args['host_id']
# _host = host.get_host_extend_info(host_id)
# self.write_json(0, data=_host)
# return
# except:
# self.write_json(-1)
# return
#
#
# class UpdateHostExtendInfo(SwxAuthJsonHandler):
# def post(self):
# 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
# host_id = args['host_id']
#
# if args['host_auth_mode'] == 1:
# if len(args['user_pwd']) > 0:
# try:
# ret_code, tmp_pswd = get_enc_data(args['user_pwd'])
# except Exception as e:
# self.write_json(-100)
# return
# if 0 != ret_code:
# self.write_json(ret_code)
# return
#
# args['user_pwd'] = tmp_pswd
#
# # ip = args['ip']
# # port = args['port']
# # user_name = args['user_name']
# # user_pwd = args['user_pwd']
# # cert_id = args['cert_id']
# # pro_type = args['pro_type']
# ret = host.update_host_extend_info(host_id, args)
# if ret:
# self.write_json(0)
# else:
# self.write_json(-1)
#
class GetSessionId(SwxAuthJsonHandler):
@tornado.gen.coroutine
def post(self, *args, **kwargs):
@ -826,18 +680,6 @@ class GetSessionId(SwxAuthJsonHandler):
return
auth_id = args['auth_id']
# config_list = host.get_config_list()
# ts_server_rpc_ip = '127.0.0.1'
#
# if 'ts_server_rpc_ip' in config_list:
# ts_server_rpc_ip = config_list['ts_server_rpc_ip']
# ts_server_rpc_port = 52080
# if 'ts_server_rpc_port' in config_list:
# ts_server_rpc_port = config_list['ts_server_rpc_port']
# ts_server_rpc_ip = cfg.core.rpc.ip
# ts_server_rpc_port = cfg.core.rpc.port
# url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
req = {'method': 'request_session', 'param': {'authid': auth_id}}
_yr = async_post_http(req)
return_data = yield _yr
@ -891,17 +733,14 @@ class AdminGetSessionId(SwxAuthJsonHandler):
tmp_auth_info['account_lock'] = 0
tmp_auth_info['account_name'] = user['name']
# ts_server_rpc_ip = cfg.core.rpc.ip
# ts_server_rpc_port = cfg.core.rpc.port
with tmp_auth_id_lock:
global tmp_auth_id_base
tmp_auth_id_base -= 1
auth_id = tmp_auth_id_base
# 将这个临时认证信息放到session中备后续查找使用10秒内有效
web_session().set('tmp-auth-info-{}'.format(auth_id), tmp_auth_info, 10)
# url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
req = {'method': 'request_session', 'param': {'authid': auth_id}}
_yr = async_post_http(req)
return_data = yield _yr
@ -959,15 +798,11 @@ class AdminFastGetSessionId(SwxAdminJsonHandler):
self.write_json(-2)
return
# ts_server_rpc_ip = cfg.core.rpc.ip
# ts_server_rpc_port = cfg.core.rpc.port
if tmp_auth_info['auth_mode'] == 1:
if len(_user_pswd) == 0: # 修改登录用户信息时可能不会修改密码,因此页面上可能不会传来密码,需要从数据库中直接读取
h = host.get_host_auth_info(_host_auth_id)
tmp_auth_info['user_auth'] = h['user_auth']
else: # 如果页面上修改了密码或者新建账号时设定了密码那么需要先交给core服务进行加密
# url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
req = {'method': 'enc', 'param': {'p': _user_pswd}}
_yr = async_post_http(req)
return_data = yield _yr
@ -996,7 +831,6 @@ class AdminFastGetSessionId(SwxAdminJsonHandler):
web_session().set('tmp-auth-info-{}'.format(auth_id), tmp_auth_info, 10)
# url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
req = {'method': 'request_session', 'param': {'authid': auth_id}}
_yr = async_post_http(req)
return_data = yield _yr
@ -1069,17 +903,6 @@ class SysUserAdd(SwxAuthJsonHandler):
args['user_pswd'] = return_data['data']
# try:
# ret_code, tmp_pswd = get_enc_data(user_pswd)
# except Exception as e:
# self.write_json(ret_code)
# return
# if 0 != ret_code:
# self.write_json(ret_code)
# return
#
# args['user_pswd'] = tmp_pswd
if host.sys_user_add(args) < 0:
return self.write_json(-1)
@ -1118,16 +941,6 @@ class SysUserUpdate(SwxAuthJsonHandler):
cert_id = kv['cert_id']
if auth_mode == 1 and user_pswd is not None:
# try:
# ret_code, tmp_pswd = get_enc_data(user_pswd)
# except Exception as e:
# self.write_json(-100)
# return
# if 0 != ret_code:
# self.write_json(ret_code)
# return
#
# args['kv']['user_pswd'] = tmp_pswd
_yr = async_enc(user_pswd)
return_data = yield _yr
if return_data is None:
@ -1154,7 +967,7 @@ class SysUserDelete(SwxAuthJsonHandler):
return
try:
host_auth_id = args['host_auth_id']
except Exception as e:
except IndexError:
self.write_json(-2)
return

View File

@ -13,4 +13,3 @@ class ExitHandler(SwxBaseHandler):
def get(self):
self.write('exit ok')
tornado.ioloop.IOLoop.instance().stop()
# sys.exit(0)

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# import sys
# import tornado.ioloop
from .base import SwxBaseHandler

View File

@ -1,15 +1,8 @@
import json
import urllib
import gzip
import os
# from .configs import app_cfg
from eom_app.app.configs import app_cfg
from eom_app.module import host
from .base import SwxJsonHandler, SwxAuthHandler
# -*- coding: utf-8 -*-
cfg = app_cfg()
from .base import SwxAuthHandler
class IndexHandler(SwxAuthHandler):
def get(self):
self.render('pwd/index.mako')
self.render('pwd/index.mako')

View File

@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
import ctypes
import json
import os
import platform
from eom_app.app.configs import app_cfg
from eom_app.module import host
# from eom_app.module import host
from eom_app.module import record
from eom_app.module import user
from .base import SwxAdminHandler, SwxAdminJsonHandler
@ -35,12 +36,15 @@ class LogHandler(SwxAdminHandler):
user_list = user.get_user_list()
total_size, free_size = get_free_space_bytes(cfg.data_path)
# ts_server = dict()
# ts_server['ip'] = cfg.core.rpc.ip
# ts_server['port'] = cfg.core.rpc.port
ts_server = '""'
# ts_server = '""'
param = {
'user_list': user.get_user_list(),
'total_size': total_size,
'free_size': free_size,
}
self.render('log/index.mako', user_list=user_list, total_size=total_size, free_size=free_size, ts_server=ts_server)
# self.render('log/index.mako', user_list=user_list, total_size=total_size, free_size=free_size, ts_server=ts_server)
self.render('log/index.mako', page_param=json.dumps(param))
class RecordHandler(SwxAdminHandler):
@ -50,8 +54,6 @@ class RecordHandler(SwxAdminHandler):
return
elif protocol == 2:
self.render('log/record.mako', record_id=record_id)
return
pass
# class PlayRdpHandler(SwxAdminHandler):
@ -68,25 +70,27 @@ class RecordHandler(SwxAdminHandler):
class ComandLogHandler(SwxAdminHandler):
def get(self, protocol, record_id):
param = dict()
param['count'] = 0
param['op'] = list()
protocol = int(protocol)
if protocol == 1:
return
pass
elif protocol == 2:
record_path = os.path.join(cfg.data_path, 'replay', 'ssh', '{:06d}'.format(int(record_id)))
file_info = os.path.join(record_path, 'tp-ssh-cmd.txt')
try:
file = open(file_info, 'r')
data = file.read()
data = file.readlines()
for i in range(len(data)):
param['op'].append({'t': data[i][1:20], 'c': data[i][22:-1]})
except:
self.write('open file error {}'.format(file_info))
return
# "Content-Type": "text/html; charset=UTF-8",
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
if len(data) == 0:
self.write('该用户没有操作')
else:
self.write(data)
return
pass
param['count'] = len(param['op'])
self.render('log/record-ssh-cmd.mako', page_param=json.dumps(param))
class RecordGetHeader(SwxAdminJsonHandler):
@ -121,17 +125,15 @@ class RecordGetInfo(SwxAdminJsonHandler):
class DeleteLog(SwxAdminJsonHandler):
# TODO: 用户可能会批量删除大量录像文件因此io操作可能会比较耗时这里应该改为异步方式。
def post(self):
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
log_list = args['log_list']
data = record.delete_log(log_list)
if data is None:
if not record.delete_log(log_list):
return self.write_json(-1)
self.write_json(0, data=data)
self.write_json(0)
class LogList(SwxAdminJsonHandler):

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# import tornado.web
import tornado.gen
import json
@ -20,7 +19,6 @@ class RpcHandler(SwxJsonHandler):
@tornado.gen.coroutine
def get(self):
_uri = self.request.uri.split('?', 1)
print(_uri)
if len(_uri) != 2:
self.write_json(-1, message='need request param.')
return
@ -39,7 +37,6 @@ class RpcHandler(SwxJsonHandler):
@tornado.gen.coroutine
def _dispatch(self, req):
print('rpc-req:', req)
try:
_req = json.loads(req)
@ -78,11 +75,9 @@ class RpcHandler(SwxJsonHandler):
if authid > 0:
# 根据authid从数据库中查询对应的数据然后返回给调用者
x = host.get_auth_info(param['authid'])
print('get_auth_info():', x)
self.write_json(0, data=x)
elif authid < 0:
x = web_session().taken('tmp-auth-info-{}'.format(authid), None)
print('get_auth_info():', x)
self.write_json(0, data=x)
else:
self.write_json(-1, message='invalid auth id.')
@ -91,15 +86,6 @@ class RpcHandler(SwxJsonHandler):
if 'sid' not in param:
return self.write_json(-1, message='invalid request.')
# jreq["param"]["sid"] = info.sid.c_str();
# jreq["param"]["account_name"] = info.account_name.c_str();
# jreq["param"]["host_ip"] = info.host_ip.c_str();
# jreq["param"]["sys_type"] = info.sys_type;
# jreq["param"]["host_port"] = info.host_port;
# jreq["param"]["auth_mode"] = info.auth_mode,
# jreq["param"]["user_name"] = info.user_name.c_str();
# jreq["param"]["protocol"] = info.protocol;
try:
_sid = param['sid']
_acc_name = param['account_name']
@ -147,7 +133,6 @@ class RpcHandler(SwxJsonHandler):
return self.write_json(return_data['code'])
cfg.update_core(return_data['data'])
print(cfg.core)
self.write_json(0)

View File

@ -87,8 +87,8 @@ class IndexHandler(SwxAdminHandler):
# cfg_list['ts_server_telnet_enabled'] = 1 if cfg.core.telnet.enabled else 0
# self.render('set/index.mako', config_list=cfg_list)
page_param = json.dumps({'core_server': cfg.core})
self.render('set/index.mako', page_param=page_param)
param = {'core_server': cfg.core}
self.render('set/index.mako', page_param=json.dumps(param))
def _restart_func():

View File

@ -84,12 +84,11 @@ def get_all_host_info_list(filter, order, limit, with_pwd=False):
','.join(['b.{}'.format(i) for i in field_b]),
_where, _order, _limit)
# print(str_sql)
db_ret = sql_exec.ExecProcQuery(str_sql)
if db_ret is None:
return 0, None
ret = list()
host = dict()
for item in db_ret:
x = DbItem()
x.load(item, ['a_{}'.format(i) for i in field_a] +
@ -524,14 +523,12 @@ def get_host_auth_info(host_auth_id):
'WHERE a.id = {}'.format(
','.join(['a.{}'.format(i) for i in field_a]),
','.join(['b.{}'.format(i) for i in field_b]), host_auth_id)
# print(str_sql)
db_ret = sql_exec.ExecProcQuery(str_sql)
if db_ret is None or len(db_ret) != 1:
return None
x = DbItem()
x.load(db_ret[0], ['a_{}'.format(i) for i in field_a] + ['b_{}'.format(i) for i in field_b])
print(x)
h = dict()
h['host_ip'] = x.b_host_ip
@ -553,7 +550,6 @@ def get_host_auth_info(host_auth_id):
h['user_auth'] = x.a_user_pswd
# user_auth = x.a_user_auth
if x.a_auth_mode == 1:
h['user_auth'] = x.a_user_pswd
elif x.a_auth_mode == 2:
@ -715,7 +711,6 @@ def sys_user_add(args):
'user_pswd,cert_id, encrypt, log_time) ' \
'VALUES ({},{},\'{}\',\'{}\',\'{}\',{},{}, \'{}\')'.format(host_id, auth_mode, user_name, user_param,
'', 0, encrypt, log_time)
# print(str_sql)
ret = sql_exec.ExecProcNonQuery(str_sql)
if not ret:
return -101

View File

@ -6,6 +6,7 @@ import struct
from .common import *
from eom_app.app.configs import app_cfg
from eom_common.eomcore.logger import log
cfg = app_cfg()
@ -176,6 +177,7 @@ def read_record_info(record_id, file_id):
break
except Exception as e:
log.e('failed to read record file: {}\n'.format(file_info))
return None
finally:
if file is not None:
@ -185,13 +187,17 @@ def read_record_info(record_id, file_id):
def delete_log(log_list):
try:
sql_exec = get_db_con()
where = list()
for item in log_list:
where.append(' id={}'.format(item))
str_sql = 'DELETE FROM ts_log WHERE{};'.format(' OR'.join(where))
ret = get_db_con().ExecProcNonQuery(str_sql)
if not ret:
return False
for item in log_list:
log_id = int(item)
str_sql = 'DELETE FROM ts_log WHERE id={}'.format(log_id)
ret = sql_exec.ExecProcNonQuery(str_sql)
if not ret:
return False
try:
record_path = os.path.join(cfg.data_path, 'replay', 'ssh', '{:06d}'.format(log_id))
if os.path.exists(record_path):

View File

@ -35,10 +35,11 @@ def modify_pwd(old_pwd, new_pwd, user_id):
def get_user_list():
# TODO: 用户管理页面不需要列出超级管理员,但是日志查看页面需要,所以应该有参数来区分不同的请求。
sql_exec = get_db_con()
field_a = ['account_id', 'account_type', 'account_name', 'account_status', 'account_lock', 'account_desc']
# string_sql = 'SELECT {} FROM ts_account as a WHERE account_type<100;'.format(','.join(['a.{}'.format(i) for i in field_a]))
string_sql = 'SELECT {} FROM ts_account as a;'.format(','.join(['a.{}'.format(i) for i in field_a]))
string_sql = 'SELECT {} FROM ts_account as a WHERE account_type<100;'.format(','.join(['a.{}'.format(i) for i in field_a]))
# string_sql = 'SELECT {} FROM ts_account as a;'.format(','.join(['a.{}'.format(i) for i in field_a]))
db_ret = sql_exec.ExecProcQuery(string_sql)
ret = list()
for item in db_ret:

View File

@ -22,7 +22,7 @@ var g_join_group_dlg = null;
ywl.do_upload_file = function () {
var param = {};
$.ajaxFileUpload({
url: "/host/load-file",// 需要链接到服务器地址
url: "/host/upload-import",// 需要链接到服务器地址
secureuri: false,
fileElementId: "upload-file", // 文件选择框的id属性
dataType: 'text', // 服务器返回的格式可以是json
@ -243,29 +243,24 @@ ywl.on_init = function (cb_stack, cb_args) {
update_file.trigger('click');
});
$('#btn-batch-export-host').click(function (e) {
console.log('xxxxxx');
ywl.ajax_post_json('/host/export-host', {},
function (ret) {
console.log('ret', ret);
if (ret.code == 0) {
var url = ret.data.url;
window.location.href = url;
ywl.notify_success('操作成功');
} else {
ywl.notify_error('操作失败');
}
// var update_args = {host_lock: host_lock};
// tbl.update_row(row_id, update_args);
},
function () {
ywl.notify_error('操作失败');
}
);
window.location.href = '/host/export-host';
// ywl.ajax_post_json('/host/export-host', {},
// function (ret) {
// console.log('ret', ret);
// if (ret.code == 0) {
// var url = ret.data.url;
// window.location.href = url;
// ywl.notify_success('操作成功');
// } else {
// ywl.notify_error('操作失败');
// }
// },
// function () {
// ywl.notify_error('操作失败');
// }
// );
});
$("#btn-apply-group").click(function () {
@ -400,9 +395,9 @@ ywl.on_host_table_created = function (tbl) {
} else if (col_key == 'auth_list') {
row_data = tbl.get_row(row_id);
$(cell_obj).find('[data-action="remote"]').click(function () {
var ts_rdp_port = ywl.page_options.ts_server.rdp_port;
var ts_ssh_port = ywl.page_options.ts_server.ssh_port;
var ts_telnet_port = ywl.page_options.ts_server.telnet_port;
var ts_rdp_port = ywl.page_options.core.rdp_port;
var ts_ssh_port = ywl.page_options.core.ssh_port;
var ts_telnet_port = ywl.page_options.core.telnet_port;
var host_ip = row_data.host_ip;
var host_port = 0;
var pro_type = parseInt($(this).attr('data-protocol'));
@ -431,12 +426,12 @@ ywl.on_host_table_created = function (tbl) {
} else if (pro_type == 3) {
host_port = ts_telnet_port;
} else {
ywl.notify_error("未知的服务器端口号" + row_data.pro_port);
ywl.notify_error("未知的服务器端口号" + pro_port);
return;
}
var args = {};
args.host_auth_id = host_auth_id;
args.server_ip = ywl.page_options.ts_server.ip;
args.server_ip = ywl.server_ip;
args.server_port = host_port;
args.pro_type = pro_type;
args.pro_sub = pro_sub;
@ -1070,9 +1065,9 @@ ywl.create_sys_user = function (tbl) {
if (!dlg_sys_user.check_args())
return;
var ts_rdp_port = ywl.page_options.ts_server.rdp_port;
var ts_ssh_port = ywl.page_options.ts_server.ssh_port;
var ts_telnet_port = ywl.page_options.ts_server.telnet_port;
var ts_rdp_port = ywl.page_options.core.rdp_port;
var ts_ssh_port = ywl.page_options.core.ssh_port;
var ts_telnet_port = ywl.page_options.core.telnet_port;
var server_port = 0;
var host_port = dlg_sys_user.host_port;
var protocol = dlg_sys_user.protocol;
@ -1088,7 +1083,7 @@ ywl.create_sys_user = function (tbl) {
}
var args = {};
args.server_ip = ywl.page_options.ts_server.ip;
args.server_ip = ywl.server_ip;
args.server_port = parseInt(server_port);
args.host_port = parseInt(host_port);
args.protocol = parseInt(protocol);

View File

@ -1,302 +1,163 @@
/**
* Created by ApexLiu on 2016-03-28.
*/
"use strict";
var g_login_type = 'account';
//g_reference = '${ reference }';
ywl.on_init = function (cb_stack, cb_args) {
ywl.login_type = ywl.page_options.login_type;
g_login_type = ywl.page_options.login_type;
if(ywl.page_options.user_name.length > 0) {
if (ywl.page_options.user_name.length > 0) {
$('#username_account').val(ywl.page_options.user_name);
}
$('#captcha_image').attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha_image').attr('src', '/auth/get-captcha?' + Math.random());
ywl.app = ywl.create_app();
cb_stack
.add(ywl.app.init)
.exec();
ywl.app = ywl.create_app();
cb_stack
.add(ywl.app.init)
.exec();
};
ywl.create_app = function () {
var _app = {};
var _app = {};
_app.dom_login_quick = null;
_app.dom_login_account = null;
_app.dom_login_account = null;
_app.init = function (cb_stack, cb_args) {
_app.dom_login_quick = $('#login-type-quick');
_app.dom_login_account = $('#login-type-account');
_app.init = function (cb_stack, cb_args) {
_app.dom_login_account = $('#login-type-account');
_app.dom_login_quick.click(function (e) {
_app.dom_login_account.removeClass('selected');
$(this).addClass('selected');
$('#input-area-account').slideUp(100);
$('#input-area-quick').slideDown(100);
});
_app.dom_login_account.click(function (e) {
_app.dom_login_quick.removeClass('selected');
$(this).addClass('selected');
$('#input-area-quick').slideUp(100);
$('#input-area-account').slideDown(100);
});
$('#btn-login-account').click(_app.login_account);
if (ywl.assist.is_logon) {
$('#input-area-quick' + ' .quick-yes').show();
$('#quick-username').html(ywl.assist.user_name);
_app.dom_login_quick.trigger('click');
} else {
$('#input-area-quick' + ' .quick-no').show();
_app.dom_login_account.trigger('click');
}
$('#captcha_image').click(function () {
$(this).attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha').focus();
});
$('#username_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#password_account').focus();
}
});
$('#password_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#captcha').focus();
}
});
$('#captcha').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
_app.login_account();
}
});
$('#btn-login-quick').click(_app.login_quick);
$('#btn-login-account').click(_app.login_account);
cb_stack.exec();
};
$('#captcha_image').click(function () {
$(this).attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha').focus();
});
$('#username_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#password_account').focus();
}
});
$('#password_account').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#captcha').focus();
}
});
$('#username_usbkey').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#password_usbkey').focus();
}
});
$('#password_usbkey').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
$('#captcha').focus();
}
});
$('#captcha').keydown(function (event) {
$('[data-toggle="popover"]').popover('hide');
if (event.which == 13) {
_app.login_account();
}
});
_app.login_account = function () {
var str_username = '';
var str_password = '';
var str_captcha = '';
cb_stack.exec();
};
var dom_username = $('#username_account');
var dom_password = $('#password_account');
var dom_captcha = $('#captcha');
_app.login_quick = function () {
if (!ywl.assist.is_logon) {
return;
}
_app.do_quick_login(ywl.assist.user_id, ywl.assist.ticket);
};
str_username = dom_username.val();
str_password = dom_password.val();
str_captcha = dom_captcha.val();
_app.login_account = function () {
var str_username = '';
var str_password = '';
var str_captcha = '';
if (str_username.length == 0) {
show_op_box('error', '缺少账号!');
dom_username.attr('data-content', "请填写您的账号!").popover('show');
dom_username.focus();
return;
}
var dom_username = $('#username_' + ywl.login_type);
var dom_password = $('#password_' + ywl.login_type);
var dom_captcha = $('#captcha');
if (str_password.length == 0) {
show_op_box('error', '缺少密码!');
dom_password.attr('data-content', "请填写密码!").popover('show');
dom_password.focus();
return;
}
str_username = dom_username.val();
str_password = dom_password.val();
str_captcha = dom_captcha.val();
if (str_captcha.length != 4) {
show_op_box('error', '验证码错误!');
dom_captcha.attr('data-content', "验证码为4位数字和字母的组合请重新填写").popover('show').focus();
return;
}
if (str_username.length == 0) {
show_op_box('error', '缺少账号!');
dom_username.attr('data-content', "请填写您的账号!").popover('show');
dom_username.focus();
return;
}
$('#btn_login').attr('disabled', 'disabled');
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在进行身份认证,请稍候...');
if (str_password.length == 0) {
show_op_box('error', '缺少密码!');
dom_password.attr('data-content', "请填写密码!").popover('show');
dom_password.focus();
return;
}
// 先判断一下captcha是否正确如果不正确拒绝登录
$.ajax({
type: 'GET',
url: '/auth/verify-captcha',
jsonp: "callback",
//jsonpCallback:"login_ret",
data: {captcha: str_captcha},
dataType: 'jsonp',
success: function (data) {
if (data.code == 0) {
// 验证成功
hide_op_box();
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在登录TELEPORT请稍候...');
_app.do_account_login(str_username, str_password, str_captcha);
}
else {
hide_op_box();
show_op_box('error', '验证码错误!');
// renew the captcha.
//change_captcha();
$('#captcha_image').attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha').focus().val('');
}
if (str_captcha.length != 4) {
show_op_box('error', '验证码错误!');
dom_captcha.attr('data-content', "验证码为4位数字和字母的组合请重新填写").popover('show').focus();
return;
}
$('#btn_login').removeAttr('disabled');
},
error: function () {
hide_op_box();
show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
$('#btn_login').removeAttr('disabled');
}
});
};
$('#btn_login').attr('disabled', 'disabled');
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在进行身份认证,请稍候...');
_app.do_account_login = function (username, userpwd, captcha) {
// 先判断一下captcha是否正确如果不正确拒绝登录
$.ajax({
type: 'GET',
url: '/auth/verify-captcha',
jsonp: "callback",
//jsonpCallback:"login_ret",
data: {captcha: str_captcha},
dataType: 'jsonp',
success: function (data) {
if (data.code == 0) {
// 验证成功
hide_op_box();
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在登录TELEPORT请稍候...');
//var ticket = data.data.ticket;
//var user_id = data.data.user_id;
_app.do_account_login(str_username, str_password, str_captcha);
$.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');
}
//_app.do_auth(ywl.login_type, str_username, str_password, str_captcha);
}
else {
hide_op_box();
show_op_box('error', '验证码错误!');
// renew the captcha.
//change_captcha();
$('#captcha_image').attr('src', '/auth/get-captcha?' + Math.random());
$('#captcha').focus().val('');
}
$('#btn_login').removeAttr('disabled');
},
error: function () {
hide_op_box();
show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
$('#btn_login').removeAttr('disabled');
}
});
};
$('#btn_login').removeAttr('disabled');
},
error: function () {
hide_op_box();
show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
$('#btn_login').removeAttr('disabled');
}
});
};
_app.do_quick_login = function (uid, ticket) {
log.v('quick');
$.ajax({
type: 'GET',
url: '/auth/quick-login',
jsonp: "callback",
data: {uid: uid, ticket: ticket},
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');
}
});
};
_app.do_auth = function (login_type, username, password, captcha) {
// 开始Ajax调用
$.ajax({
type: 'GET',
url: 'http://127.0.0.1:50021/login',
jsonp: "callback",
data: {login_type: login_type, username: username, password: password},
dataType: 'jsonp',
success: function (data) {
if (data.code == 0) {
// 登录成功了
hide_op_box();
show_op_box('wait', '<i class="fa fa-circle-o-notch fa-spin"></i> 正在登录TELEPORT请稍候...');
var ticket = data.data.ticket;
var user_id = data.data.user_id;
_app.do_account_login(user_id, username, ticket, captcha);
}
else {
hide_op_box();
show_op_box('error', data.data.err_msg);
}
$('#btn_login').removeAttr('disabled');
},
error: function () {
hide_op_box();
show_op_box(login_type, 'error', '很抱歉,身份认证失败!请稍后再试一次!');
$('#btn_login').removeAttr('disabled');
}
});
};
_app.do_account_login = function (username, userpwd, captcha) {
$.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;
return _app;
};
function change_login_type(login_type) {
if (login_type == g_login_type)
return;
$('#login_' + login_type).show('fast');
$('#login_' + g_login_type).hide('fast');
$('#login_type_' + login_type).addClass('selected');
$('#login_type_' + g_login_type).removeClass('selected');
if (login_type == 'usbkey')
$('#btn_login').attr('disabled', 'disabled');
else
$('#btn_login').removeAttr('disabled');
g_login_type = login_type;
}
function hide_op_box() {
$('#login_message').hide();
$('#login_message').hide();
}
function show_op_box(op_type, op_msg) {
var obj_box = $('#login_message');
var obj_box = $('#login_message');
obj_box.html(op_msg);
obj_box.removeClass().addClass('op_box op_' + op_type);
obj_box.show();
obj_box.html(op_msg);
obj_box.removeClass().addClass('op_box op_' + op_type);
obj_box.show();
}

View File

@ -1,5 +1,5 @@
/*! ywl v1.0.1, (c)2015 eomsoft.net */
"use strict";
var OS_TYPE_WINDOWS = 1;
var OS_TYPE_LINUX = 2;
var PROTOCOL_TYPE_RDP = 1;
@ -8,312 +8,298 @@ var PROTOCOL_TYPE_TELNET = 3;
var AUTH_TYPE_PASSWORD = 1;
var AUTH_TYPE_SSHKEY = 2;
var AUTH_NONE = 0;
var g_assist = null;
ywl.on_init = function (cb_stack, cb_args) {
var dom_id = '#ywl_host_list';
g_assist = ywl.create_assist();
var dom_id = '#ywl_host_list';
g_assist = ywl.create_assist();
var last_version = $("#tp-assist-version").text();
var low_version = $("#tp-assist-version").attr("low-version");
var last_version = $("#tp-assist-version").text();
var low_version = $("#tp-assist-version").attr("low-version");
teleport_init(last_version, low_version, function (ret) {
$("#tp-assist-current-version").text("当前助手版本:" + ret.version);
}, function (ret, code, error) {
if (code == TP_ERR_NO_ASSIST) {
$("#tp-assist-current-version").text("未能检测到TP助手请您下载并启动TP助手")
g_assist.alert_assist_not_found();
teleport_init(last_version, low_version,
function (ret) {
$("#tp-assist-current-version").text("当前助手版本:" + ret.version);
},
function (ret, code, error) {
if (code == TP_ERR_NO_ASSIST) {
$("#tp-assist-current-version").text("未能检测到TP助手请您下载并启动TP助手")
g_assist.alert_assist_not_found();
}
else if (code == TP_ERR_VERSION_TOO_LOW) {
ywl.notify_error(error);
$('#tp-assist-current-version').html('当前助手版本太低v' + ret.version + '),请<a href="http://teleport.eomsoft.net/static/download/teleport-assist-last-win.zip">下载最新版本</a>!');
}
else {
$("#tp-assist-current-version").text(error)
ywl.notify_error(error);
}
console.log('error:', error)
}
});
else if (code == TP_ERR_VERSION_TOO_LOW) {
ywl.notify_error(error);
$('#tp-assist-current-version').html('当前助手版本太低v' + ret.version + '),请<a href="http://teleport.eomsoft.net/static/download/teleport-assist-last-win.zip">下载最新版本</a>!');
return;
}
else {
$("#tp-assist-current-version").text(error)
ywl.notify_error(error);
console.log('error:', error)
}
});
//===================================
// 创建页面控件对象
//===================================
// 表格数据
var host_table_options = {
selector: dom_id + " [ywl-table='host-list']",
data_source: {
type: 'ajax-post',
url: '/host/list'
},
column_default: {sort: false, header_align: 'center', cell_align: 'center'},
columns: [
{title: "主机", key: "host_id", width: 240, render: 'host_id', fields: {id: 'host_ip', host_desc: 'host_desc', host_port: 'host_port'}},
{title: "分组", key: "group_name", width: 180},
{title: "系统", key: "host_sys_type", width: 64, render: 'sys_type', fields: {sys_type: 'host_sys_type'}},
{title: "状态", key: "host_lock", width: 90, render: 'host_lock', fields: {host_lock: 'host_lock'}},
{title: "远程连接", key: "auth_list", header_align: 'left', cell_align: 'left', render: 'auth_list', fields: {id: 'host_id', protocol: 'protocol', auth_list: 'auth_list'}},
//===================================
// 创建页面控件对象
//===================================
// 表格数据
var host_table_options = {
selector: dom_id + " [ywl-table='host-list']",
data_source: {
type: 'ajax-post',
url: '/host/list'
},
column_default: {sort: false, header_align: 'center', cell_align: 'center'},
columns: [
{title: "主机", key: "host_id", width: 240, render: 'host_id', fields: {id: 'host_ip', host_desc: 'host_desc', host_port: 'host_port'}},
{title: "分组", key: "group_name", width: 180},
{title: "系统", key: "host_sys_type", width: 64, render: 'sys_type', fields: {sys_type: 'host_sys_type'}},
{title: "状态", key: "host_lock", width: 90, render: 'host_lock', fields: {host_lock: 'host_lock'}},
{title: "远程连接", key: "auth_list", header_align: 'left', cell_align: 'left', render: 'auth_list', fields: {id: 'host_id', protocol: 'protocol', auth_list: 'auth_list'}},
// {title: "", key: "padding"},
// {title: "操作", key: "action", width: 160, render: 'make_action_btn', fields: {id: 'host_id'}}
],
paging: {selector: dom_id + " [ywl-paging='host-list']", per_page: paging_normal},
],
paging: {selector: dom_id + " [ywl-paging='host-list']", per_page: paging_normal},
// 可用的属性设置
//have_header: true or false
// 可用的属性设置
//have_header: true or false
// 可用的回调函数
on_created: ywl.on_host_table_created,
// 可用的回调函数
on_created: ywl.on_host_table_created,
// 可重载的函数在on_created回调函数中重载
// on_render_created
// on_header_created
// on_paging_created
// on_data_loaded
// on_row_rendered
// on_table_rendered
// on_cell_created
// on_begin_load
// on_after_load
// 可重载的函数在on_created回调函数中重载
// on_render_created
// on_header_created
// on_paging_created
// on_data_loaded
// on_row_rendered
// on_table_rendered
// on_cell_created
// on_begin_load
// on_after_load
// 可用的函数
// load_data
// cancel_load
// set_data
// add_row
// remove_row
// get_row
// update_row
// clear
// reset_filter
};
// 可用的函数
// load_data
// cancel_load
// set_data
// add_row
// remove_row
// get_row
// update_row
// clear
// reset_filter
};
var host_table = ywl.create_table(host_table_options);
var host_table = ywl.create_table(host_table_options);
// 主机分组过滤器
ywl.create_table_filter_host_group(host_table, dom_id + " [ywl-filter='host-group']", ywl.page_options.group_list);
// 主机分组过滤器
ywl.create_table_filter_host_group(host_table, dom_id + " [ywl-filter='host-group']", ywl.page_options.group_list);
ywl.create_table_filter_system_type(host_table, dom_id + " [ywl-filter='system-type']");
// 搜索框
ywl.create_table_filter_search_box(host_table, dom_id + " [ywl-filter='search']");
ywl.create_table_filter_system_type(host_table, dom_id + " [ywl-filter='system-type']");
// 搜索框
ywl.create_table_filter_search_box(host_table, dom_id + " [ywl-filter='search']");
//======================================================
// 事件绑定
//======================================================
//======================================================
// 事件绑定
//======================================================
// 将刷新按钮点击事件绑定到表格的重新加载函数上,这样,点击刷新就导致表格数据重新加载。
$(dom_id + " [ywl-filter='reload']").click(host_table.reload);
// 将刷新按钮点击事件绑定到表格的重新加载函数上,这样,点击刷新就导致表格数据重新加载。
$(dom_id + " [ywl-filter='reload']").click(host_table.reload);
cb_stack
.add(host_table.load_data)
.add(host_table.init)
.exec();
cb_stack
.add(host_table.load_data)
.add(host_table.init)
.exec();
};
// 扩展/重载表格的功能
ywl.on_host_table_created = function (tbl) {
tbl.on_cell_created = function (row_id, col_key, cell_obj) {
var row_data = tbl.get_row(row_id);
if (col_key == 'host_pro_type') {
console.log('row-data', row_data);
$(cell_obj).find('[data-action="remote"]').click(function () {
var ts_rdp_port = ywl.page_options.ts_server.rdp_port;
var ts_ssh_port = ywl.page_options.ts_server.ssh_port;
var port = 0;
var pro_type = row_data.host_pro_type;
if (pro_type === 1) {
port = ts_rdp_port;
} else if (pro_type === 2) {
port = ts_ssh_port;
} else {
return;
}
var args = {};
args.auth_id = row_data.auth_id;
args.server_ip = ywl.page_options.ts_server.ip;
args.port = port;
args.pro_type = pro_type;
args.pro_sub = $(this).attr('data-sub-protocol');
args.host_ip = row_data.host_ip;
args.size = 2;
to_teleport(
'/host/get-session-id',
args,
function () {
console.log('远程连接建立成功!')
},
function (code, error) {
if (code == TP_ERR_NO_ASSIST)
g_assist.alert_assist_not_found();
else {
ywl.notify_error(error);
console.log('error:', error)
}
}
);
});
} else if (col_key == 'auth_list') {
console.log('row-data', row_data);
$(cell_obj).find('[data-action="remote"]').click(function () {
var ts_rdp_port = ywl.page_options.ts_server.rdp_port;
var ts_ssh_port = ywl.page_options.ts_server.ssh_port;
var ts_telnet_port = ywl.page_options.ts_server.telnet_port;
console.log("row_data", row_data);
console.log('page-option', ywl.page_options);
var pro_type = parseInt($(this).attr('data-protocol'));
var pro_sub = parseInt($(this).attr('data-sub-protocol'));
var auth_id = parseInt($(this).attr('auth-id'));
var host_ip = row_data.host_ip;
var server_port = 0;
var size = 0;
var rdp_console = 0;
if (pro_type == 1) {
server_port = ts_rdp_port;
size = parseInt($(this).parent().parent().find('#dlg-rdp-size select').val())
if ($(this).parent().parent().find('#dlg-action-rdp-console').is(':checked')) {
rdp_console = 1;
} else {
rdp_console = 0;
}
} else if (pro_type == 2) {
server_port = ts_ssh_port;
} else if (pro_type == 3) {
server_port = ts_telnet_port;
} else {
ywl.notify_error("未知的服务器端口号" + row_data.pro_port);
return;
}
var args = {};
args.auth_id = auth_id;
args.server_ip = ywl.page_options.ts_server.ip;
args.server_port = server_port;
args.pro_type = pro_type;
args.pro_sub = pro_sub;
args.host_ip = host_ip;
args.size = size;
args.console = rdp_console;
console.log('args', args);
to_teleport(
'/host/get-session-id',
args,
function () {
console.log('远程连接建立成功!')
},
function (code, error) {
if (code == TP_ERR_NO_ASSIST)
g_assist.alert_assist_not_found();
else {
ywl.notify_error(error);
console.log('error:', error)
}
}
);
});
}
};
tbl.on_cell_created = function (row_id, col_key, cell_obj) {
var row_data = tbl.get_row(row_id);
if (col_key == 'host_pro_type') {
console.log('row-data', row_data);
$(cell_obj).find('[data-action="remote"]').click(function () {
var ts_rdp_port = ywl.page_options.core.rdp_port;
var ts_ssh_port = ywl.page_options.core.ssh_port;
var port = 0;
var pro_type = row_data.host_pro_type;
if (pro_type === 1) {
port = ts_rdp_port;
} else if (pro_type === 2) {
port = ts_ssh_port;
} else {
return;
}
var args = {};
args.auth_id = row_data.auth_id;
args.server_ip = ywl.server_ip;
args.port = port;
args.pro_type = pro_type;
args.pro_sub = $(this).attr('data-sub-protocol');
args.host_ip = row_data.host_ip;
args.size = 2;
to_teleport(
'/host/get-session-id',
args,
function () {
console.log('远程连接建立成功!')
},
function (code, error) {
if (code == TP_ERR_NO_ASSIST)
g_assist.alert_assist_not_found();
else {
ywl.notify_error(error);
console.log('error:', error)
}
}
);
});
} else if (col_key == 'auth_list') {
// console.log('row-data', row_data);
$(cell_obj).find('[data-action="remote"]').click(function () {
var ts_rdp_port = ywl.page_options.core.rdp_port;
var ts_ssh_port = ywl.page_options.core.ssh_port;
var ts_telnet_port = ywl.page_options.core.telnet_port;
// console.log("row_data", row_data);
// console.log('page-option', ywl.page_options);
var pro_type = parseInt($(this).attr('data-protocol'));
var pro_sub = parseInt($(this).attr('data-sub-protocol'));
var auth_id = parseInt($(this).attr('auth-id'));
var host_ip = row_data.host_ip;
var server_port = 0;
var size = 0;
var rdp_console = 0;
if (pro_type == 1) {
server_port = ts_rdp_port;
size = parseInt($(this).parent().parent().find('#dlg-rdp-size select').val())
if ($(this).parent().parent().find('#dlg-action-rdp-console').is(':checked')) {
rdp_console = 1;
} else {
rdp_console = 0;
}
} else if (pro_type == 2) {
server_port = ts_ssh_port;
} else if (pro_type == 3) {
server_port = ts_telnet_port;
} else {
ywl.notify_error("未知的服务器端口号" + row_data.pro_port);
return;
}
var args = {};
args.auth_id = auth_id;
args.server_ip = ywl.server_ip;
args.server_port = server_port;
args.pro_type = pro_type;
args.pro_sub = pro_sub;
args.host_ip = host_ip;
args.size = size;
args.console = rdp_console;
// console.log('args', args);
to_teleport('/host/get-session-id', args,
function () {
console.log('远程连接建立成功!')
},
function (code, error) {
if (code == TP_ERR_NO_ASSIST)
g_assist.alert_assist_not_found();
else {
ywl.notify_error(error);
console.log('error:', error)
}
}
);
});
}
};
// 重载表格渲染器的部分渲染方式,加入本页面相关特殊操作
tbl.on_render_created = function (render) {
render.host_id = function (row_id, fields) {
var ret = [];
ret.push('<span class="host-id" href="javascript:;">' + fields.id + ':' + fields.host_port + '</span>');
ret.push('<a class="host-desc" href="javascript:;" ywl-host-desc="' + fields.id + '">' + fields.host_desc + '</a>');
return ret.join('');
};
// 重载表格渲染器的部分渲染方式,加入本页面相关特殊操作
tbl.on_render_created = function (render) {
render.host_id = function (row_id, fields) {
var ret = [];
ret.push('<span class="host-id" href="javascript:;">' + fields.id + ':' + fields.host_port + '</span>');
ret.push('<a class="host-desc" href="javascript:;" ywl-host-desc="' + fields.id + '">' + fields.host_desc + '</a>');
return ret.join('');
};
render.auth_list = function (row_id, fields) {
render.auth_list = function (row_id, fields) {
var auth_list = fields.auth_list;
var ret = [];
var protocol = fields.protocol;
for (var i = 0; i < auth_list.length; i++) {
var auth = auth_list[i];
// TODO: 新版本应该返回一个数组,这里应该根据一个数组合成多个用户的连接按钮
var auth_list = fields.auth_list;
var ret = [];
var protocol = fields.protocol;
for (var i = 0; i < auth_list.length; i++) {
var auth = auth_list[i];
ret.push('<div class="remote-action-group">');
ret.push('<ul>');
ret.push('<div class="remote-action-group">');
ret.push('<ul>');
if (auth.user_name.length > 0)
ret.push('<li class="remote-action-username">' + auth.user_name + '</li>');
else
ret.push('<li class="remote-action-username">- 未指定 -</li>');
if (auth.user_name.length > 0)
ret.push('<li class="remote-action-username">' + auth.user_name + '</li>');
else
ret.push('<li class="remote-action-username">- 未指定 -</li>');
// if (auth.auth_mode == AUTH_TYPE_PASSWORD) {
// ret.push('<li class="remote-action-password">密码</li>');
// } else if (auth.auth_mode == AUTH_TYPE_SSHKEY) {
// ret.push('<li class="remote-action-sshkey">私钥</li>');
// } else if (auth.auth_mode == AUTH_NONE) {
// ret.push('<li class="remote-action-noauth">无</li>');
// } else {
// ret.push('<li class="remote-action-noauth">未知</li>');
// }
switch (protocol) {
case PROTOCOL_TYPE_RDP:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="1" data-sub-protocol="1"><i class="fa fa-desktop fa-fw"></i> RDP</a></li>');
ret.push('<li class="remote-action-input" id="dlg-rdp-size"><select>');
ret.push('<option value=1>800x600</option>');
ret.push('<option value=2 selected="selected">1024x768</option>');
ret.push('<option value=3>1280x1024</option>');
ret.push('<option value=0>全屏</option>');
ret.push('</select></li>');
ret.push('<li><label><input type="checkbox" id="dlg-action-rdp-console"> Console</label></li>');
break;
case PROTOCOL_TYPE_SSH:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="2" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> SSH</a></li>');
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-success" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="2" data-sub-protocol="2"><i class="fa fa-upload fa-fw"></i> SFTP</a></li>');
break;
case PROTOCOL_TYPE_TELNET:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="3" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> TELNET</a></li>');
break;
default:
ret.push('<li>未知协议类型</li>');
}
ret.push('</ul>');
ret.push('</div>');
}
switch (protocol) {
case PROTOCOL_TYPE_RDP:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="1" data-sub-protocol="1"><i class="fa fa-desktop fa-fw"></i> RDP</a></li>');
ret.push('<li class="remote-action-input" id="dlg-rdp-size"><select>');
ret.push('<option value=1>800x600</option>');
ret.push('<option value=2 selected="selected">1024x768</option>');
ret.push('<option value=3>1280x1024</option>');
ret.push('<option value=0>全屏</option>');
ret.push('</select></li>');
ret.push('<li><label><input type="checkbox" id="dlg-action-rdp-console"> Console</label></li>');
break;
case PROTOCOL_TYPE_SSH:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="2" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> SSH</a></li>');
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-success" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="2" data-sub-protocol="2"><i class="fa fa-upload fa-fw"></i> SFTP</a></li>');
break;
case PROTOCOL_TYPE_TELNET:
ret.push('<li class="remote-action-btn"><a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" auth-id=' + auth.auth_id + ' host-auth-id=' + auth.host_auth_id + ' data-protocol="3" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> TELNET</a></li>');
break;
default:
ret.push('<li>未知协议类型</li>');
}
ret.push('</ul>');
ret.push('</div>');
}
return ret.join('');
};
render.host_lock = function (row_id, fields) {
switch (fields.host_lock) {
case 0:
return '<span class="badge badge-success">正常</span>';
case 1:
return '<span class="badge badge-danger">禁止连接</span>';
default:
return '<span class="badge badge-danger">未知</span>';
}
};
render.pro_type = function (row_id, fields) {
switch (fields.pro_type) {
case 1:
return '<a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-desktop fa-fw"></i> RDP</a>';
case 2:
var ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> SSH</a>');
ret.push('<a href="javascript:;" class="btn btn-sm btn-success" data-action="remote" data-sub-protocol="2"><i class="fa fa-upload fa-fw"></i> SFTP</a>');
ret.push('</div>');
return ret.join('');
default:
return '<span class="badge badge-danger">未知协议</span>';
}
};
return ret.join('');
};
render.make_action_btn = function (row_id, fields) {
var ret = [];
render.host_lock = function (row_id, fields) {
switch (fields.host_lock) {
case 0:
return '<span class="badge badge-success">正常</span>';
case 1:
return '<span class="badge badge-danger">禁止连接</span>';
default:
return '<span class="badge badge-danger">未知</span>';
}
};
render.pro_type = function (row_id, fields) {
switch (fields.pro_type) {
case 1:
return '<a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-desktop fa-fw"></i> RDP</a>';
case 2:
var ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<a href="javascript:;" class="btn btn-sm btn-primary" data-action="remote" data-sub-protocol="1"><i class="fa fa-keyboard-o fa-fw"></i> SSH</a>');
ret.push('<a href="javascript:;" class="btn btn-sm btn-success" data-action="remote" data-sub-protocol="2"><i class="fa fa-upload fa-fw"></i> SFTP</a>');
ret.push('</div>');
return ret.join('');
default:
return '<span class="badge badge-danger">未知协议</span>';
}
};
ret.push('<div class="btn-group btn-group-sm">');
ret.push('<a href="javascript:;" class="btn btn-primary" ywl-btn-action="' + fields.id + '"><i class="fa fa-desktop fa-fw"></i> 远程连接</a>');
ret.push('</div>');
return ret.join('');
}
render.make_action_btn = function (row_id, fields) {
var ret = [];
ret.push('<div class="btn-group btn-group-sm">');
ret.push('<a href="javascript:;" class="btn btn-primary" ywl-btn-action="' + fields.id + '"><i class="fa fa-desktop fa-fw"></i> 远程连接</a>');
ret.push('</div>');
return ret.join('');
}
};
};
};

View File

@ -8,6 +8,8 @@ var YWL = {
self.assist = null;
self.page_options = {};
self.server_ip = window.location.hostname || '';
self.add_page_options = function (options) {
_.extend(self.page_options, options);
};

View File

@ -26,22 +26,7 @@
<div class="col-md-5">
<div class="auth-box auth-box-lg">
<div class="header">
<a id="login-type-account" class="title" href="javascript:void(0);">账号/密码 登录</a>
## <a id="login_type_usbkey" class="title" href="javascript:void(0);" onclick="change_login_type('usbkey');">USB-Key 登录</a>
</div>
<div id="input-area-quick" class="quick-area" style="display: none;">
<div class="quick-yes" style="display: none;">
<div class="quick-disc">请点击头像进行快速登录!</div>
<a id="btn-login-quick" class="quick-account" href="javascript:void(0);">
<span class="quick-image"><i class="fa fa-male fa-fw"></i></span>
<span id="quick-username" class="label label-primary quick-name">User Name</span>
</a>
</div>
<div class="quick-no" style="display: none;">
<div class="quick-disc">未发现已登录账号,无法进行快速登录!</div>
</div>
<div id="login-type-account" class="title selected">账号/密码 登录</div>
</div>
<div id="input-area-account" class="inputarea">
@ -56,32 +41,12 @@
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span>
<input id="password_account" type="password" class="form-control" placeholder="密码"
data-toggle="popover" data-trigger="manual" data-placement="top">
<input id="password_account" type="password" class="form-control" placeholder="密码" data-toggle="popover" data-trigger="manual" data-placement="top">
</div>
</div>
</div>
<div id="login_usbkey" class="login-usbkey" style="display:none;">
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-user fa-fw"></i></span>
<input id="username_usbkey" type="text" class="form-control" placeholder="账号,支持邮箱/手机号" value="设备查找中..." disabled>
</div>
<p id="usbkey_message" class="op_box op_wait"><i class="fa fa-circle-o-notch fa-spin"></i> 正在查找USB-Key请稍候...</p>
</div>
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span>
<input id="password_usbkey" type="password" class="form-control" placeholder="USB-Key设备密码">
</div>
</div>
</div>
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-check-square-o fa-fw"></i></span>

View File

@ -597,16 +597,15 @@
<%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({
## 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

@ -56,9 +56,7 @@
<div class="input-group input-group-sm" ywl-filter="search" style="display:inline-block;">
<input type="text" class="form-control" placeholder="搜索 ID 或 IP" style="display:inline-block;">
<span class="input-group-btn" style="display:inline-block;margin-left:-4px;">
<button type="button" class="btn btn-default"><i class="fa fa-search fa-fw"></i></button>
</span>
<span class="input-group-btn" style="display:inline-block;margin-left:-4px;"><button type="button" class="btn btn-default"><i class="fa fa-search fa-fw"></i></button></span>
</div>
</div>
@ -70,9 +68,6 @@
<!-- begin page-nav -->
<div class="page-nav" ywl-paging="host-list">
## <div style="float:left;">
## <a href="https://127.0.0.1:50022/" target="_blank" class="btn btn-sm btn-danger"><i class="fa fa-info-circle fa-fw"></i> TELEPORT助手状态</a>
## </div>
<div class="" style="float:right;">
<nav>
@ -101,24 +96,6 @@
</div>
<!-- end of box -->
<!-- begin box -->
## <div class="box">
## <div class="box-license">
## <div style="float:right;"><a href="#" class="btn btn-sm btn-primary"><i class="fa fa-plus-circle fa-fw"></i> 增加主机授权</a></div>
## <div class="breadcrumb-container">
## <ol class="breadcrumb">
## <li><i class="fa fa-server fa-fw"></i> 授权主机数:<strong>120</strong></li>
## <li>已激活主机数:<strong>118</strong></li>
## </ol>
## </div>
##
## </div>
## </div>
<!-- end of box -->
</div>
@ -127,52 +104,12 @@
<%block name="extend_content">
## <div class="popover-inline-edit">
## <div class="popover fade bottom in" role="tooltip" ywl-dlg="modify-host-desc" style="display:none;">
## <div class="arrow" style="left:50px;"></div>
## <h3 class="popover-title">为主机 <span ywl-field="host-id"></span> 添加备注,以便识别</h3>
## <div class="popover-content">
## <div style="display:inline-block;float:right;">
## <a href="javascript:;" class="btn btn-success btn-sm" ywl-btn="ok"><i class="glyphicon glyphicon-ok"></i></a>
## <a href="javascript:;" class="btn btn-danger btn-sm" ywl-btn="cancel"><i class="glyphicon glyphicon-remove"></i></a>
## </div>
## <div style="padding-right:80px;">
## <input type="text" ywl-input="desc" class="form-control" value="">
## <input type="hidden" ywl-input="ywl-row-index" value="">
## </div>
## </div>
## </div>
## </div>
</%block>
<%block name="embed_js">
<script type="text/javascript">
// var host_dt = null;
ywl.add_page_options({
// 有些参数由后台python脚本生成到模板中无法直接生成到js文件中所以必须通过这种方式传递参数到js脚本中。
group_list: ${group_list},
ts_server: ${ts_server}
});
$(document).ready(function () {
## var ywl_options = {
## active_menu: ${self.attr.page_menu_}
## };
##
## ywl.add_page_options(ywl_options);
// $('#username_account').keydown(function(event) { $('[data-toggle="popover"]').popover('hide'); if(event.which == 13) { $('#password_account').focus(); } });
// $('#password_account').keydown(function(event) { $('[data-toggle="popover"]').popover('hide'); if(event.which == 13) { $('#captcha').focus(); } });
// $('#username_usbkey').keydown(function(event) { $('[data-toggle="popover"]').popover('hide'); if(event.which == 13) { $('#password_usbkey').focus(); } });
// $('#password_usbkey').keydown(function(event) { $('[data-toggle="popover"]').popover('hide'); if(event.which == 13) { $('#captcha').focus(); } });
// $('#captcha').keydown(function(event) { $('[data-toggle="popover"]').popover('hide'); if(event.which == 13) { login(); } });
});
ywl.add_page_options(${page_param});
</script>
</%block>

View File

@ -1,140 +1,100 @@
<%!
page_title_ = '日志查询'
page_menu_ = ['log']
page_id_ = 'log'
page_title_ = '日志查询'
page_menu_ = ['log']
page_id_ = 'log'
%>
<%inherit file="../page_base.mako"/>
<%block name="extend_js">
<script type="text/javascript" src="${ static_url('js/ui/teleport.js') }"></script>
<script type="text/javascript" src="${ static_url('js/ui/log.js') }"></script>
## <script type="text/javascript" src="${ static_url('js/ui/teleport.js') }"></script>
<script type="text/javascript" src="${ static_url('js/ui/log.js') }"></script>
</%block>
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
<ol class="breadcrumb">
<li><i class="fa fa-server fa-fw"></i> ${self.attr.page_title_}</li>
</ol>
</%block>
## Begin Main Body.
<div class="page-content">
<!-- begin box -->
<div class="box" id="ywl_log_list">
<!-- begin filter -->
<div class="page-filter">
<div class="" style="float:right;">
<!-- begin box -->
<div class="box" id="ywl_log_list">
<!-- begin filter -->
<div class="page-filter">
<div class="" style="float:right;">
<span id="disk-status" class="badge badge-info" style="margin-right:10px;">磁盘状态</span>
<a href="javascript:;" class="btn btn-sm btn-primary" ywl-filter="reload"><i
class="fa fa-repeat fa-fw"></i> 刷新</a>
<a href="javascript:;" class="btn btn-sm btn-primary" ywl-filter="reload"><i class="fa fa-repeat fa-fw"></i> 刷新</a>
</div>
</div>
<div class="">
<div class="">
<div class="input-group input-group-sm" style="display:inline-block;margin-right:10px;">
<span class="input-group-addon"
style="display:inline-block;width:auto; line-height:28px;height:30px;padding:0 10px;font-size:13px;">用户名</span>
<div class="input-group-btn" ywl-filter="user-name" style="display:inline-block;margin-left:-4px;">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span>所有</span> <span class="caret"></span></button>
<ul class="dropdown-menu">
<li>所有</li>
</ul>
</div>
</div>
<div class="input-group input-group-sm" style="display:inline-block;margin-right:10px;">
<span class="input-group-addon" style="display:inline-block;width:auto; line-height:28px;height:30px;padding:0 10px;font-size:13px;">用户名</span>
<div class="input-group-btn" ywl-filter="user-name" style="display:inline-block;margin-left:-4px;">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span>所有</span> <span class="caret"></span></button>
<ul class="dropdown-menu">
<li>所有</li>
</ul>
</div>
</div>
<div class="input-group input-group-sm" ywl-filter="search" style="display:inline-block;">
<input type="text" class="form-control" placeholder="搜索 ID 或 IP" style="display:inline-block;">
<div class="input-group input-group-sm" ywl-filter="search" style="display:inline-block;">
<input type="text" class="form-control" placeholder="搜索 ID 或 IP" style="display:inline-block;">
<span class="input-group-btn" style="display:inline-block;margin-left:-4px;">
<button type="button" class="btn btn-default"><i class="fa fa-search fa-fw"></i></button>
</span>
</div>
</div>
</div>
</div>
<!-- end filter -->
</div>
</div>
<!-- end filter -->
<table class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"
ywl-table="log-list"></table>
<table class="table table-striped table-bordered table-hover table-data no-footer dtr-inline" ywl-table="log-list"></table>
<!-- begin page-nav -->
<div class="page-nav" ywl-paging="log-list">
<div style="float:left;">
<a href="#" id="delete-log" class="btn btn-sm btn-danger"><i class="fa fa-plus-circle fa-fw"></i> 批量删除日志</a>
</div>
<!-- begin page-nav -->
<div class="page-nav" ywl-paging="log-list">
<div style="float:left;">
<a href="#" id="delete-log" class="btn btn-sm btn-danger"><i class="fa fa-plus-circle fa-fw"></i> 批量删除日志</a>
</div>
<div class="" style="float:right;">
<nav>
<ul class="pagination pagination-sm"></ul>
</nav>
</div>
<div class="" style="float:right;">
<nav>
<ul class="pagination pagination-sm"></ul>
</nav>
</div>
<div style="float:right;margin-right:30px;">
<div class="breadcrumb-container">
<ol class="breadcrumb">
<li><i class="fa fa-list fa-fw"></i> 记录总数 <strong ywl-field="recorder_total">0</strong></li>
<li>页数 <strong><span ywl-field="page_current">1</span>/<span
ywl-field="page_total">1</span></strong></li>
<li>每页显示
<label>
<select></select>
</label>
条记录
</li>
</ol>
</div>
</div>
<div style="float:right;margin-right:30px;">
<div class="breadcrumb-container">
<ol class="breadcrumb">
<li><i class="fa fa-list fa-fw"></i> 记录总数 <strong ywl-field="recorder_total">0</strong></li>
<li>页数 <strong><span ywl-field="page_current">1</span>/<span
ywl-field="page_total">1</span></strong></li>
<li>每页显示
<label>
<select></select>
</label>
条记录
</li>
</ol>
</div>
</div>
</div>
<!-- end page-nav -->
</div>
<!-- end page-nav -->
</div>
<!-- end of box -->
<!-- begin box -->
## <div class="box">
## <div class="box-btn-bar">
## <div style="float:right;">
## <a href="#" id="delete-log" class="btn btn-sm btn-danger"><i class="fa fa-plus-circle fa-fw"></i> 批量删除日志</a>
## </div>
## <div class="clear-float"></div>
##
## </div>
## </div>
<!-- end of box -->
</div>
<!-- end of box -->
</div>
<%block name="extend_content">
</%block>
<%block name="embed_js">
<script type="text/javascript">
ywl.add_page_options({
// 有些参数由后台python脚本生成到模板中无法直接生成到js文件中所以必须通过这种方式传递参数到js脚本中。
user_list: ${user_list},
total_size: ${total_size},
free_size: ${free_size},
ts_server: ${ts_server},
});
$(document).ready(function () {
});
</script>
<script type="text/javascript">
ywl.add_page_options(${page_param});
</script>
</%block>

View File

@ -0,0 +1,101 @@
<%!
page_title_ = '操作记录'
%>
<%inherit file="../page_no_sidebar_base.mako"/>
<%block name="extend_js">
</%block>
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server"></i> ${self.attr.page_title_}</li>
</ol>
</%block>
<%block name="extend_css">
<style type="text/css">
#no-op-msg {
display: none;
padding: 20px;
margin: 50px;
background-color: #fffed5;
border-radius: 5px;
font-size: 120%;
}
#op-list {
display: none;
padding: 20px;
margin: 20px 10px 20px 10px;
background-color: #ffffff;
font-size: 14px;
border-radius: 5px;
}
.op-item {
margin-bottom: 3px;
}
.time, .cmd {
font-family: Consolas, Lucida Console, Monaco, Courier, 'Courier New', monospace;
line-height: 15px;
padding: 0 5px;
border-radius: 3px;
}
.time {
margin-right: 15px;
background-color: #d8d8d8;
}
.cmd-danger {
background-color: #ffbba6;
font-weight: bold;
}
.cmd-info {
background-color: #b4fdb1;
}
</style>
</%block>
<div class="page-content">
<div id="no-op-msg">
他悄悄地来,又悄悄地走,挥一挥衣袖,没有留下任何操作~~~~
</div>
<div id="op-list"></div>
</div>
<%block name="embed_js">
<script type="text/javascript">
ywl.add_page_options(${page_param});
var danger_cmd = ['rm', 'su', 'sudo'];
var info_cmd = ['exit'];
ywl.on_init = function (cb_stack, cb_args) {
if (ywl.page_options.count == 0) {
$('#no-op-msg').show();
} else {
var dom_op_list = $('#op-list');
var html = [];
for (var i = 0; i < ywl.page_options.count; i++) {
var cmd_list = ywl.page_options.op[i].c.split(' ');
var cmd_class = '';
if (_.intersection(cmd_list, danger_cmd).length > 0) {
cmd_class = ' cmd-danger';
} else if (_.intersection(cmd_list, info_cmd).length > 0) {
cmd_class = ' cmd-info';
}
html.push('<div class="op-item"><span class="time">' + ywl.page_options.op[i].t + '</span> <span class="cmd' + cmd_class + '">' + ywl.page_options.op[i].c + '</span></li></div>');
}
dom_op_list.append(html.join(''));
dom_op_list.show();
}
cb_stack.exec();
};
</script>
</%block>

View File

@ -10,7 +10,7 @@
<%block name="breadcrumb">
<ol class="breadcrumb">
<li><i class="fa fa-server"></i> 录像回放</li>
<li><i class="fa fa-server"></i> ${self.attr.page_title_}</li>
</ol>
</%block>
@ -41,13 +41,8 @@
<%block name="embed_js">
<script type="text/javascript">
ywl.add_page_options({
// 有些参数由后台python脚本生成到模板中无法直接生成到js文件中所以必须通过这种方式传递参数到js脚本中。
record_id:${record_id}
});
$(document).ready(function () {
});
</script>
</%block>