(未完成)加入第三方服务集成所需密钥管理界面及数据库表

feature/assist-websocket
Apex Liu 2022-05-27 05:07:21 +08:00
parent 916b82d649
commit 8b106a8be6
16 changed files with 1436 additions and 673 deletions

View File

@ -155,7 +155,7 @@ class BuilderWin(BuilderBase):
installer = os.path.join(PATH_DOWNLOAD, file_name)
if not os.path.exists(installer):
if not utils.download_file('openssl installer', 'http://slproweb.com/download/{}'.format(filename), PATH_DOWNLOAD, file_name):
if not utils.download_file('openssl installer', 'http://slproweb.com/download/{}'.format(file_name), PATH_DOWNLOAD, file_name):
cc.e('can not download pre-built installer of OpenSSL.')
return

View File

@ -23,6 +23,13 @@
"cmdline": "-newtab \"TP#ssh://{real_ip}\" -url ssh://{user_name}:****@{host_ip}:{host_port}",
"desc": []
},
{
"name": "mobaxterm",
"display": "MobaXterm",
"app": "",
"cmdline": "-newtab \"sshpass -p**** ssh {user_name}@{host_ip} -p {host_port}\"",
"desc": []
},
{
"name": "other",
"display": "自定义",

View File

@ -20,7 +20,7 @@
"vs_path": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community",
"wget": "",
"7z": "",
"nsis": ""
"nsis": ""
},

View File

@ -21,11 +21,15 @@ $app.on_init = function (cb_stack) {
$app.storage = $app.create_config_storage();
cb_stack.add($app.storage.init);
$app.integration = $app.create_config_integration();
cb_stack.add($app.integration.init);
cb_stack.add($app.load_role_list);
cb_stack.exec();
};
$app.create_info_table = function () {
var _info = {};
let _info = {};
_info.dom = {
web_info: $('#web-info-kv'),
@ -33,7 +37,7 @@ $app.create_info_table = function () {
};
_info.init = function (cb_stack) {
var h = [];
let h = [];
h.push(_info._make_info('WEB服务版本', $app.options.web_cfg.version));
@ -79,7 +83,7 @@ $app.create_info_table = function () {
_info._make_protocol_info = function (name, p) {
if (_.isUndefined(p))
return _info._make_info(name, '未能检测到');
var val = p.port;
let val = p.port;
if (!p.enable) {
val = '<span class="disabled">' + val + '(未启用)</span>';
}
@ -91,7 +95,7 @@ $app.create_info_table = function () {
};
$app.create_dlg_result = function () {
var _dlg = {};
let _dlg = {};
_dlg.dom = {
dlg: $('#dlg-result'),
@ -109,7 +113,7 @@ $app.create_dlg_result = function () {
};
$app.create_config_smtp = function () {
var _smtp = {};
let _smtp = {};
_smtp.dom = {
server: $('#smtp-server-info'),
@ -154,7 +158,7 @@ $app.create_config_smtp = function () {
_smtp.update_dom = function (smtp) {
if (0 === smtp.server.length) {
var not_set = '<span class="error">未设置</span>';
let not_set = '<span class="error">未设置</span>';
_smtp.dom.server.html(not_set);
_smtp.dom.port.html(not_set);
_smtp.dom.ssl.html(not_set);
@ -168,7 +172,7 @@ $app.create_config_smtp = function () {
};
_smtp.on_edit = function () {
var smtp = $app.options.sys_cfg.smtp;
let smtp = $app.options.sys_cfg.smtp;
_smtp.dom.input_server.val(smtp.server);
@ -211,12 +215,12 @@ $app.create_config_smtp = function () {
};
_smtp.on_btn_send = function () {
var _server = _smtp.dom.input_server.val();
var _port = _smtp.dom.input_port.val();
var _sender = _smtp.dom.input_sender.val();
var _password = _smtp.dom.input_password.val();
var _recipient = _smtp.dom.input_recipient.val();
var _ssl = _smtp.dom.input_ssl.hasClass('tp-selected');
let _server = _smtp.dom.input_server.val();
let _port = _smtp.dom.input_port.val();
let _sender = _smtp.dom.input_sender.val();
let _password = _smtp.dom.input_password.val();
let _recipient = _smtp.dom.input_recipient.val();
let _ssl = _smtp.dom.input_ssl.hasClass('tp-selected');
if (!_smtp._check_input(_server, _port, _sender, _password))
return;
@ -254,11 +258,11 @@ $app.create_config_smtp = function () {
};
_smtp.on_btn_save = function () {
var _server = _smtp.dom.input_server.val();
var _port = _smtp.dom.input_port.val();
var _sender = _smtp.dom.input_sender.val();
var _password = _smtp.dom.input_password.val();
var _ssl = _smtp.dom.input_ssl.hasClass('tp-selected');
let _server = _smtp.dom.input_server.val();
let _port = _smtp.dom.input_port.val();
let _sender = _smtp.dom.input_sender.val();
let _password = _smtp.dom.input_password.val();
let _ssl = _smtp.dom.input_ssl.hasClass('tp-selected');
if (!_smtp._check_input(_server, _port, _sender, _password))
return;
@ -304,7 +308,7 @@ $app.create_config_smtp = function () {
};
$app.create_config_sec = function () {
var _sec = {};
let _sec = {};
_sec.dom = {
btn_save: $('#btn-save-secure-config'),
@ -383,15 +387,15 @@ $app.create_config_sec = function () {
};
_sec.on_btn_save = function () {
var _password_allow_reset = _sec.dom.btn_password_allow_reset.hasClass('tp-selected');
var _password_force_strong = _sec.dom.btn_password_force_strong.hasClass('tp-selected');
var _password_timeout = parseInt(_sec.dom.input_password_timeout.val());
let _password_allow_reset = _sec.dom.btn_password_allow_reset.hasClass('tp-selected');
let _password_force_strong = _sec.dom.btn_password_force_strong.hasClass('tp-selected');
let _password_timeout = parseInt(_sec.dom.input_password_timeout.val());
var _login_session_timeout = parseInt(_sec.dom.input_session_timeout.val());
var _login_retry = parseInt(_sec.dom.input_login_retry.val());
var _login_lock_timeout = parseInt(_sec.dom.input_lock_timeout.val());
let _login_session_timeout = parseInt(_sec.dom.input_session_timeout.val());
let _login_retry = parseInt(_sec.dom.input_login_retry.val());
let _login_lock_timeout = parseInt(_sec.dom.input_lock_timeout.val());
var _login_auth = 0;
let _login_auth = 0;
// if (_sec.dom.btn_auth_username_password.hasClass('tp-selected'))
// _login_auth |= TP_LOGIN_AUTH_USERNAME_PASSWORD;
if (_sec.dom.btn_auth_username_password_captcha.hasClass('tp-selected'))
@ -500,7 +504,7 @@ $app.create_config_sec = function () {
};
$app.create_config_sess = function () {
var _sess = {};
let _sess = {};
_sess.dom = {
btn_save: $('#btn-save-session-config'),
@ -556,23 +560,23 @@ $app.create_config_sess = function () {
};
_sess.on_btn_save = function () {
var flag_record = 0;
let flag_record = 0;
flag_record |= TP_FLAG_RECORD_REPLAY; // now we always need record replay.
flag_record |= TP_FLAG_RECORD_REAL_TIME; // not implement, set this flag for default.
var flag_rdp = 0;
let flag_rdp = 0;
flag_rdp |= TP_FLAG_RDP_DESKTOP; // before support remote-app, remote-desktop is the only way to access remote host.
if(_sess.dom.btn_sess_rdp_allow_clipboard.hasClass('tp-selected'))
if (_sess.dom.btn_sess_rdp_allow_clipboard.hasClass('tp-selected'))
flag_rdp |= TP_FLAG_RDP_CLIPBOARD;
if(_sess.dom.btn_sess_rdp_allow_disk.hasClass('tp-selected'))
if (_sess.dom.btn_sess_rdp_allow_disk.hasClass('tp-selected'))
flag_rdp |= TP_FLAG_RDP_DISK;
if(_sess.dom.btn_sess_rdp_allow_console.hasClass('tp-selected'))
if (_sess.dom.btn_sess_rdp_allow_console.hasClass('tp-selected'))
flag_rdp |= TP_FLAG_RDP_CONSOLE;
var flag_ssh = 0;
if(_sess.dom.btn_sess_ssh_allow_shell.hasClass('tp-selected'))
let flag_ssh = 0;
if (_sess.dom.btn_sess_ssh_allow_shell.hasClass('tp-selected'))
flag_ssh |= TP_FLAG_SSH_SHELL;
if(_sess.dom.btn_sess_ssh_allow_sftp.hasClass('tp-selected'))
if (_sess.dom.btn_sess_ssh_allow_sftp.hasClass('tp-selected'))
flag_ssh |= TP_FLAG_SSH_SFTP;
if (flag_ssh === 0) {
@ -580,7 +584,7 @@ $app.create_config_sess = function () {
return;
}
var _noop_timeout = parseInt(_sess.dom.input_noop_timeout.val());
let _noop_timeout = parseInt(_sess.dom.input_noop_timeout.val());
if (_.isNaN(_noop_timeout) || _noop_timeout < 0 || _noop_timeout > 60) {
@ -632,7 +636,7 @@ $app.create_config_sess = function () {
};
$app.create_config_storage = function () {
var _sto = {};
let _sto = {};
_sto.dom = {
storage_size: $('#storage-size'),
@ -648,7 +652,7 @@ $app.create_config_storage = function () {
_sto.init = function (cb_stack) {
// 当前会话录像存储空间:总 123.35GB,可用空间 85.17GB。
var _info = [];
let _info = [];
if (!$app.options.core_cfg.detected) {
_sto.dom.storage_size.removeClass().addClass('alert alert-danger');
_info.push('未能连接到核心服务,无法获取存储空间信息!');
@ -668,7 +672,7 @@ $app.create_config_storage = function () {
_sto.on_btn_cleanup();
});
_sto.dom.btn_export_db.click(function() {
_sto.dom.btn_export_db.click(function () {
_sto.on_export_db();
});
@ -683,11 +687,11 @@ $app.create_config_storage = function () {
};
_sto.on_btn_save = function () {
var _keep_log = parseInt(_sto.dom.input_keep_log.val());
var _keep_record = parseInt(_sto.dom.input_keep_record.val());
let _keep_log = parseInt(_sto.dom.input_keep_log.val());
let _keep_record = parseInt(_sto.dom.input_keep_record.val());
var _cleanup_hour = parseInt(_sto.dom.select_cleanup_hour.val());
var _cleanup_minute = parseInt(_sto.dom.select_cleanup_minute.val());
let _cleanup_hour = parseInt(_sto.dom.select_cleanup_hour.val());
let _cleanup_minute = parseInt(_sto.dom.select_cleanup_minute.val());
if (!(_keep_log === 0 || (_keep_log >= 30 && _keep_log <= 365))) {
$tp.notify_error('日志保留时间超出范围!');
@ -734,8 +738,8 @@ $app.create_config_storage = function () {
};
_sto.on_btn_cleanup = function () {
var _keep_log = parseInt(_sto.dom.input_keep_log.val());
var _keep_record = parseInt(_sto.dom.input_keep_record.val());
let _keep_log = parseInt(_sto.dom.input_keep_log.val());
let _keep_record = parseInt(_sto.dom.input_keep_record.val());
if ($app.options.sys_cfg.storage.keep_log !== _keep_log || $app.options.sys_cfg.storage.keep_record !== _keep_record) {
$tp.notify_error('您已经修改了设置,请先保存设置,再进行清理!');
@ -751,11 +755,10 @@ $app.create_config_storage = function () {
function (ret) {
_sto.dom.btn_cleanup.removeAttr('disabled');
if (ret.code === TPE_OK) {
console.log(ret);
$tp.notify_success('清理存储空间成功!');
var msg = [];
for (var i = 0; i < ret.data.length; ++i) {
let msg = [];
for (let i = 0; i < ret.data.length; ++i) {
msg.push('<p>' + ret.data[i] + '</p>');
}
@ -772,9 +775,402 @@ $app.create_config_storage = function () {
);
};
_sto.on_export_db = function() {
_sto.on_export_db = function () {
window.location.href = '/system/export-db';
};
return _sto;
};
$app.create_config_integration = function () {
let _obj = {};
_obj.dom = {
btn_refresh_integration: $('#btn-refresh-integration'),
btn_add_integration: $('#btn-add-integration'),
select_all_integration: $('#table-integration-select-all'),
btn_remove_integration: $('#btn-remove-integration'),
};
_obj.init = function (cb_stack) {
_obj.dlg_edit_integration = _obj.create_dlg_edit_integration();
cb_stack.add(_obj.dlg_edit_integration.init);
_obj.dom.btn_add_integration.click(function () {
_obj.dlg_edit_integration.show_create();
});
//-------------------------------
// 第三方集成配置列表表格
//-------------------------------
let table_integration_options = {
dom_id: 'table-integration',
data_source: {
type: 'ajax-post',
url: '/system/get-integration'
},
message_no_data: '尚未配置外部服务集成密钥...',
column_default: {sort: false, align: 'left'},
columns: [
{
// title: '<a href="javascript:" data-reset-filter><i class="fa fa-undo fa-fw"></i></a>',
title: '',
key: 'chkbox',
width: 36,
align: 'center',
render: 'make_check_box',
fields: {id: 'id'}
},
{
title: '服务名称',
key: 'name',
width: 120,
},
{
title: 'Access Key',
key: 'acc_key',
width: 160,
render: 'acc_key',
// fields: {acc_key: 'acc_key'}
},
{
title: '备注',
key: 'comment',
},
{
title: '权限角色',
key: 'role_name',
width: 120,
},
{
title: '',
key: 'action',
align: 'center',
width: 200,
render: 'make_action_btn',
fields: {id: 'id'}
}
],
// 重载回调函数
on_render_created: _obj.on_table_integration_render_created,
on_cell_created: _obj.on_table_integration_cell_created
};
_obj.table_integration = $tp.create_table(table_integration_options);
cb_stack
.add(_obj.table_integration.load_data)
.add(_obj.table_integration.init);
_obj.dom.btn_refresh_integration.click(function () {
_obj.table_integration.load_data();
});
_obj.dom.select_all_integration.click(function () {
let _objects = $('#' + _obj.table_integration.dom_id + ' tbody').find('[data-check-box]');
if ($(this).is(':checked')) {
$.each(_objects, function (i, _obj) {
$(_obj).prop('checked', true);
});
} else {
$.each(_objects, function (i, _obj) {
$(_obj).prop('checked', false);
});
}
});
_obj.dom.btn_remove_integration.click(function () {
_obj.on_btn_remove_integration_click();
});
cb_stack.exec();
};
_obj.on_table_integration_cell_created = function (tbl, row_id, col_key, cell_obj) {
if (col_key === 'chkbox') {
cell_obj.find('[data-check-box]').click(function () {
_obj.check_integration_all_selected();
});
} else if (col_key === 'action') {
let _row_id = row_id;
cell_obj.find('[data-btn-edit]').click(function () {
_obj.dlg_edit_integration.show_edit(_row_id);
});
cell_obj.find('[data-btn-remove]').click(function () {
_obj.on_btn_remove_integration_click(_row_id);
});
}
};
_obj.on_table_integration_render_created = function (render) {
render.make_check_box = function (row_id, fields) {
return '<span><input type="checkbox" data-check-box="' + fields.id + '" data-row-id="' + row_id + '"></span>';
};
render.acc_key = function (row_id, fields) {
return '<span class="mono">' + fields.acc_key + '</span>';
};
render.make_action_btn = function (row_id, fields) {
let ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<btn class="btn btn-primary" data-btn-edit="edit"><i class="fa fa-edit"></i> 编辑</btn>');
ret.push('<btn class="btn btn-danger" data-btn-remove="' + fields.id + '"><i class="fas fa-trash-alt"></i> 删除</btn>');
ret.push('</div>');
return ret.join('');
};
};
_obj.check_integration_all_selected = function () {
let _all_checked = true;
let _objs = $('#' + _obj.table_integration.dom_id + ' tbody').find('[data-check-box]');
$.each(_objs, function (i, _obj) {
if (!$(_obj).is(':checked')) {
_all_checked = false;
return false;
}
});
if (_all_checked) {
_obj.dom.select_all_integration.prop('checked', true);
} else {
_obj.dom.select_all_integration.prop('checked', false);
}
};
_obj.get_selected_integration = function (tbl) {
let items = [];
let _objs = $('#' + _obj.table_integration.dom_id + ' tbody tr td input[data-check-box]');
$.each(_objs, function (i, _obj) {
if ($(_obj).is(':checked')) {
let _row_data = tbl.get_row(_obj);
items.push(_row_data);
}
});
return items;
};
_obj.on_btn_remove_integration_click = function (_row_id) {
let remove_list = [];
if (_.isUndefined(_row_id)) {
let items = _obj.get_selected_integration(_obj.table_integration);
if (items.length === 0) {
$tp.notify_error('请选择要删除的外部密钥!');
return;
}
$.each(items, function (i, g) {
remove_list.push(g.id);
});
} else {
let _row_data = _obj.table_integration.get_row(_row_id);
remove_list.push(_row_data.id);
}
let _fn_sure = function (cb_stack, cb_args) {
$tp.ajax_post_json('/system/remove-integration', {items: remove_list},
function (ret) {
if (ret.code === TPE_OK) {
_obj.table_integration.load_data();
$tp.notify_success('删除外部密钥操作成功!');
} else {
$tp.notify_error('删除外部密钥操作失败:' + tp_error_msg(ret.code, ret.message));
}
cb_stack.exec();
},
function () {
$tp.notify_error('网络故障,删除外部密钥操作失败!');
cb_stack.exec();
}
);
};
let cb_stack = CALLBACK_STACK.create();
let _msg_remove = '您确定要移除此外部密钥吗?';
if (remove_list.length > 1)
_msg_remove = '您确定要移除选定的 <strong>' + remove_list.length + '个</strong> 外部密钥吗?';
$tp.dlg_confirm(cb_stack, {
msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除外部密钥会导致使用这些外部密钥的第三方应用再也无法调用Teleport的API接口</p></div><p>' + _msg_remove + '</p>',
fn_yes: _fn_sure
});
};
_obj.create_dlg_edit_integration = function () {
let dlg = {};
dlg.dom_id = 'dlg-edit-integration';
dlg.field_id = -1; // 密钥id仅编辑模式
dlg.field_acc_key = ''; // access-key仅编辑模式
dlg.field_role = -1;
dlg.field_name = '';
dlg.field_comment = '';
dlg.dom = {
dialog: $('#' + dlg.dom_id)
, dlg_title: $('#' + dlg.dom_id + ' [data-field="dlg-title"]')
, select_role: $('#edit-integration-role')
, edit_name: $('#edit-integration-name')
, edit_comment: $('#edit-integration-comment')
, btn_save: $('#btn-edit-integration-save')
, area_regenerate: $('#area-integration-regenerate')
, chk_regenerate: $('#chk-integration-regenerate')
};
dlg.init = function (cb_stack) {
// 创建角色选择框
let _ret = [
'<button type="button" class="btn btn-sm dropdown-toggle" data-toggle="dropdown">',
'<span data-selected-role>选择角色</span> <i class="fa fa-caret-right"></i></button>',
'<ul class="dropdown-menu dropdown-menu-sm">'
];
$.each($app.role_list, function (i, role) {
_ret.push('<li><a href="javascript:;" data-tp-selector="' + role.id + '"><i class="fa fa-user-circle fa-fw"></i> ' + role.name + '</a></li>');
});
_ret.push('</ul>');
dlg.dom.select_role.after($(_ret.join('')));
// 动态创建的dom对象需要创建完成后再绑定。
dlg.dom.selected_role = $('#' + dlg.dom_id + ' span[data-selected-role]');
// 绑定角色选择框事件
$('#' + dlg.dom_id + ' li a[data-tp-selector]').click(function () {
let select = parseInt($(this).attr('data-tp-selector'));
if (dlg.field_role === select)
return;
let name = $app.role_id2name(select);
if (_.isUndefined(name)) {
name = '选择角色';
dlg.field_role = -1;
} else {
dlg.field_role = select;
}
dlg.dom.selected_role.text(name);
});
dlg.dom.btn_save.click(dlg.on_save);
cb_stack.exec();
};
dlg.init_fields = function (data) {
let role_name = '选择角色';
dlg.field_role = -1;
if (_.isUndefined(data)) {
dlg.dom.dlg_title.html('创建外部密钥');
dlg.field_id = -1;
dlg.field_acc_key = '';
dlg.dom.edit_name.val('');
dlg.dom.edit_comment.val('');
dlg.dom.area_regenerate.hide();
} else {
dlg.field_id = data.id;
dlg.field_acc_key = data.acc_key;
dlg.dom.dlg_title.html('编辑外部密钥:<span class="mono">' + data.acc_key + '</span>');
let _name = $app.role_id2name(data.role_id);
if (!_.isUndefined(_name)) {
role_name = _name;
dlg.field_role = data.role_id;
}
dlg.dom.edit_name.val(data.name);
dlg.dom.edit_comment.val(data.comment);
dlg.dom.chk_regenerate.prop('checked', false);
dlg.dom.area_regenerate.show();
}
dlg.dom.selected_role.text(role_name);
};
dlg.show_create = function () {
dlg.init_fields();
dlg.dom.dialog.modal({backdrop: 'static'});
};
dlg.show_edit = function (row_id) {
let data = _obj.table_integration.get_row(row_id);
// console.log(data);
dlg.init_fields(data);
dlg.dom.dialog.modal({backdrop: 'static'});
};
dlg.check_input = function () {
dlg.field_name = dlg.dom.edit_name.val();
dlg.field_comment = dlg.dom.edit_comment.val();
if (dlg.field_role === -1) {
$tp.notify_error('请为外部密钥指定一个权限角色!');
return false;
}
if (dlg.field_name.length === 0) {
dlg.dom.edit_name.focus();
$tp.notify_error('请为外部密钥设置一个名称!');
return false;
}
return true;
};
dlg.on_save = function () {
if (!dlg.check_input())
return;
let action = (dlg.field_id === -1) ? '创建' : '更新';
let timeout = (dlg.field_id === -1) ? 60000 : 30000;
let is_regenerate = dlg.dom.chk_regenerate.is(':checked');
let args = {
id: dlg.field_id,
role_id: dlg.field_role,
name: dlg.field_name,
comment: dlg.field_comment,
};
if (dlg.field_id !== -1) {
args['acc_key'] = dlg.field_acc_key;
args['regenerate'] = is_regenerate;
}
// 如果id为-1表示创建否则表示更新
$tp.ajax_post_json('/system/update-integration', args,
function (ret) {
if (ret.code === TPE_OK) {
if (ret.message.length > 0)
$tp.notify_success(ret.message);
else
$tp.notify_success('外部密钥' + action + '成功!');
_obj.table_integration.load_data();
dlg.dom.dialog.modal('hide');
if (dlg.field_id === -1 || is_regenerate) {
let msg = [
'<div class="alert alert-warning">注意Access Secret 仅显示一次,请妥善记录!</div><div>',
'<p style="padding-top:10px;"><span style="display:inline-block;width:130px;"><i class="fa fa-key fa-fw"></i> Access Key: </span><span class="mono bold">',
ret.data.acc_key,
'</span></p><p style="padding-top:10px;"><span style="display:inline-block;width:130px;"><i class="fa fa-eye-slash fa-fw"></i> Access Secret: </span><span class="mono bold">',
ret.data.acc_sec,
'</span></p></div>'
];
$app.dlg_result.show('外部密钥' + action + '成功', msg.join(''));
}
} else {
$tp.notify_error('外部密钥' + action + '失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,外部密钥' + action + '失败!');
},
timeout
);
};
return dlg;
};
return _obj;
};

View File

@ -117,7 +117,7 @@ $tp.create_table = function (options) {
// 整理传入的表格初始化参数
_tbl._fix_options = function () {
if (!_.isUndefined(_tbl.options.column_default)) {
for (var i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
for (let i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
if (!_.isUndefined(_tbl.options.columns[i]['align'])) {
if (_.isUndefined(_tbl.options.columns[i]['header_align'])) {
_tbl.options.columns[i]['header_align'] = _tbl.options.columns[i]['align'];
@ -127,7 +127,7 @@ $tp.create_table = function (options) {
}
}
for (var k in _tbl.options.column_default) {
for (let k in _tbl.options.column_default) {
if (_tbl.options.column_default.hasOwnProperty(k)) {
if (k === 'align') {
if (_.isUndefined(_tbl.options.columns[i]['header_align'])) {
@ -136,8 +136,7 @@ $tp.create_table = function (options) {
if (_.isUndefined(_tbl.options.columns[i]['cell_align'])) {
_tbl.options.columns[i]['cell_align'] = _tbl.options.column_default[k];
}
}
else if (_.isUndefined(_tbl.options.columns[i][k])) {
} else if (_.isUndefined(_tbl.options.columns[i][k])) {
_tbl.options.columns[i][k] = _tbl.options.column_default[k];
}
}
@ -230,28 +229,28 @@ $tp.create_table = function (options) {
_tbl.load_begin(1500);
var _filter = {};
let _filter = {};
// 对每一个关联的过滤器,获取其设置
$.each(_tbl.filter_ctrls, function (name, ctrl) {
if (_.isUndefined(ctrl.get_filter)) {
console.error('filter', name, 'has have no get_filter() interface.');
}
var _f = ctrl.get_filter();
let _f = ctrl.get_filter();
$.each(_f, function (k, v) {
_filter[k] = v;
});
});
var _order = null;
let _order = null;
if (_tbl.header_ctrl) {
_order = _tbl.header_ctrl.get_order();
}
var _limit = {};
let _limit = {};
_limit.page_index = _tbl.page_index;
_limit.per_page = _tbl.per_page;
var args = {filter: _filter, order: _order, limit: _limit};
let args = {filter: _filter, order: _order, limit: _limit};
if (_tbl.options.data_source && _tbl.options.data_source.restrict)
args.restrict = _tbl.options.data_source.restrict;
if (_tbl.options.data_source && _tbl.options.data_source.exclude)
@ -265,12 +264,14 @@ $tp.create_table = function (options) {
if (_tbl.options.data_source) {
if (_tbl.options.data_source.type === 'none') {
// 外部直接调用set_data()方法来设置数据,无需本控件主动获取
cb_stack.exec();
} else if (_tbl.options.data_source.type === 'callback') {
// 调用一个函数来加载数据
args.table = _tbl;
_tbl.options.data_source.fn(cb_stack, args);
cb_stack.exec();
} else if (_tbl.options.data_source.type === 'ajax-post') {
var _url = _tbl.options.data_source.url;
let _url = _tbl.options.data_source.url;
$tp.ajax_post_json(_url, args,
function (ret) {
// console.log('ajax-return:', ret);
@ -281,27 +282,31 @@ $tp.create_table = function (options) {
cb_stack.add(_tbl.load_end);
_tbl.set_data(cb_stack, {}, {total: ret.data.total, page_index: ret.data.page_index, data: ret.data.data});
}
cb_stack.exec();
},
function () {
_tbl.show_load_failed();
cb_stack.exec();
}, 6000
);
} else {
console.error('table-options [data-source] type [' + _tbl.options.data_source.type + '] known.');
cb_stack.exec();
}
} else {
console.error('have no idea for load table data. need data_source.');
cb_stack.exec();
}
};
_tbl._create_row_dom = function (row_data) {
var node = ['<tr data-row-id="' + row_data._row_id + '">'];
let node = ['<tr data-row-id="' + row_data._row_id + '">'];
for (var i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
var col = _tbl.options.columns[i];
for (let i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
let col = _tbl.options.columns[i];
node.push('<td data-cell-id="' + row_data._row_id + '-' + i + '"');
var _style = '';
let _style = '';
if (col.cell_align !== 'center') {
_style += 'text-align:' + col.cell_align + ';';
}
@ -314,12 +319,12 @@ $tp.create_table = function (options) {
node.push('>');
var k;
let k;
if (_.isUndefined(col.render)) {
if (_.isUndefined(col.fields) || _.isEmpty(col.fields)) {
node.push(row_data[col.key]);
} else {
var _tmp = [];
let _tmp = [];
for (k in col.fields) {
if (col.fields.hasOwnProperty(k))
_tmp.push(row_data[col.fields[k]]);
@ -328,7 +333,7 @@ $tp.create_table = function (options) {
}
} else {
if (_.isFunction(_tbl.render[col.render])) {
var _args = {};
let _args = {};
for (k in col.fields) {
if (col.fields.hasOwnProperty(k))
_args[k] = row_data[col.fields[k]];
@ -345,10 +350,10 @@ $tp.create_table = function (options) {
_tbl._render_row = function (row_data, pos_row_id) {
// 0=插入到第一行,-1=插入到最后一行(默认),其他=插入到指定row_id的行之后如果没有找到指定的行则插入到最后
var _pos = !_.isUndefined(pos_row_id) ? pos_row_id : -1;
let _pos = !_.isUndefined(pos_row_id) ? pos_row_id : -1;
var dom_obj = $('#' + _tbl.dom_id + ' tbody');
var _tr = $(_tbl._create_row_dom(row_data));
let dom_obj = $('#' + _tbl.dom_id + ' tbody');
let _tr = $(_tbl._create_row_dom(row_data));
_tr.data('data-row-data', row_data);
if (_pos === -1) {
@ -356,7 +361,7 @@ $tp.create_table = function (options) {
} else if (_pos === 0) {
dom_obj.prepend(_tr);
} else {
var _pos_obj = $(dom_obj).find("[data-row-id='" + _pos + "']");
let _pos_obj = $(dom_obj).find("[data-row-id='" + _pos + "']");
if (0 === _pos_obj[0]) {
// 没有找到指定行,则加入到最后
dom_obj.append(_tr);
@ -368,40 +373,40 @@ $tp.create_table = function (options) {
// callback for each cell.
if (_.isFunction(_tbl.options.on_cell_created)) {
var _cell_objs = $('#' + _tbl.dom_id + " tr[data-row-id='" + row_data._row_id + "'] td");
for (var i = 0, cnt = _cell_objs.length; i < cnt; ++i) {
let _cell_objs = $('#' + _tbl.dom_id + " tr[data-row-id='" + row_data._row_id + "'] td");
for (let i = 0, cnt = _cell_objs.length; i < cnt; ++i) {
console.log('aaaa');
_tbl.options.on_cell_created(_tbl, row_data._row_id, _tbl.options.columns[i].key, $(_cell_objs[i]));
}
}
if (_.isFunction(_tbl.options.on_row_created)) {
var _row_obj = $('#' + _tbl.dom_id + " [data-row-id='" + row_data._row_id + "']");
let _row_obj = $('#' + _tbl.dom_id + " [data-row-id='" + row_data._row_id + "']");
_tbl.options.on_row_created(_tbl, row_data._row_id, _row_obj);
}
};
_tbl._render_rows = function (rows_data, pos_row_id) {
// 0=插入到第一行,-1=插入到最后一行(默认),其他=插入到指定row_id的行之后如果没有找到指定的行则插入到最后
var _pos = !_.isUndefined(pos_row_id) ? pos_row_id : -1;
let _pos = !_.isUndefined(pos_row_id) ? pos_row_id : -1;
var dom_obj = $('#' + _tbl.dom_id + ' tbody');
var node = [];
let dom_obj = $('#' + _tbl.dom_id + ' tbody');
let node = [];
var r;
var row_count = rows_data.length;
let r;
let row_count = rows_data.length;
for (r = 0; r < row_count; ++r) {
node.push(_tbl._create_row_dom(rows_data[r]));
}
var _tr = $(node.join(''));
let _tr = $(node.join(''));
if (_pos === -1) {
dom_obj.append(_tr);
} else if (_pos === 0) {
dom_obj.prepend(_tr);
} else {
var _pos_obj = $(dom_obj).find("[data-row-id='" + _pos + "']");
let _pos_obj = $(dom_obj).find("[data-row-id='" + _pos + "']");
if (0 === _pos_obj[0]) {
// 没有找到指定行,则加入到最后
dom_obj.append(_tr);
@ -411,15 +416,15 @@ $tp.create_table = function (options) {
}
}
var _have_cell_created = _.isFunction(_tbl.options.on_cell_created);
var _have_row_created = _.isFunction(_tbl.options.on_row_created);
let _have_cell_created = _.isFunction(_tbl.options.on_cell_created);
let _have_row_created = _.isFunction(_tbl.options.on_row_created);
for (r = 0; r < row_count; ++r) {
var _row_obj = $('#' + _tbl.dom_id + ' tr[data-row-id="' + rows_data[r]._row_id + '"]');
let _row_obj = $('#' + _tbl.dom_id + ' tr[data-row-id="' + rows_data[r]._row_id + '"]');
_row_obj.data('data-row-data', rows_data[r]);
if (_have_cell_created) {
for (var i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
for (let i = 0, cnt = _tbl.options.columns.length; i < cnt; ++i) {
_tbl.options.on_cell_created(_tbl, rows_data[r]._row_id, _tbl.options.columns[i].key, $('#' + _tbl.dom_id + ' td[data-cell-id="' + rows_data[r]._row_id + '-' + i + '"]'));
}
}
@ -430,7 +435,7 @@ $tp.create_table = function (options) {
};
_tbl.render_table = function (cb_stack, cb_args) {
var dom_obj = $('#' + _tbl.dom_id + ' tbody');
let dom_obj = $('#' + _tbl.dom_id + ' tbody');
if (_tbl.row_data.length === 0) {
_tbl.show_empty_table();
@ -452,7 +457,7 @@ $tp.create_table = function (options) {
_tbl.page_total = Math.ceil(_tbl.total / _tbl.per_page);
// 我们为表格的每一行数据加入我们自己的索引 _row_id
for (var i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
for (let i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
if (_.isUndefined(_tbl.row_data[i]._row_id)) {
_tbl.row_data[i]._row_id = _.uniqueId();
}
@ -474,9 +479,9 @@ $tp.create_table = function (options) {
// 2. 行本身的JQuery对象或者行内任意一个JQuery对象
// 3. 行的id创建行时内部制定的不一定是顺序号
_tbl.get_row = function (obj) {
var _tr = null;
let _tr = null;
if (_.isElement(obj) || _.isObject(obj)) {
var _obj = _.isElement(obj) ? $(obj) : obj;
let _obj = _.isElement(obj) ? $(obj) : obj;
if (_obj.prop('tagName') === 'TR') {
_tr = _obj;
} else if (_obj.prop('tagName') === 'TD') {
@ -486,8 +491,8 @@ $tp.create_table = function (options) {
}
return _tr.data('data-row-data');
} else if (_.isString(obj) || _.isNumber(obj)) {
var _id = _.isString(obj) ? obj : '' + obj;
for (var i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
let _id = _.isString(obj) ? obj : '' + obj;
for (let i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
if (_tbl.row_data[i]._row_id === _id) {
return _tbl.row_data[i];
}
@ -502,10 +507,10 @@ $tp.create_table = function (options) {
// TODO: 更新一行数据传入的kv有可能比原始数据内容的字段更多需要能够保存下来备用
// TODO: 此外,需要检查一下表格初始化时使用的字段,如果这些字段的内容并没有更新,则无需更新界面元素,以提升性能
_tbl.update_row = function (row_id, kv) {
var _row_obj = $('#' + _tbl.dom_id + " tr[data-row-id='" + row_id + "']");
var _row_data = _row_obj.data('data-row-data');
var _changed_fields = [];
for (var k in kv) {
let _row_obj = $('#' + _tbl.dom_id + " tr[data-row-id='" + row_id + "']");
let _row_data = _row_obj.data('data-row-data');
let _changed_fields = [];
for (let k in kv) {
if (kv.hasOwnProperty(k)) {
if (!_.isUndefined(_row_data[k])) {
if (_row_data[k] !== kv[k])
@ -523,10 +528,10 @@ $tp.create_table = function (options) {
console.log('-- update row ui --');
// 根据columns的设置更新界面元素
for (var i in _tbl.options.columns) {
for (let i in _tbl.options.columns) {
if (!_tbl.options.columns.hasOwnProperty(i))
continue;
var col = _tbl.options.columns[i];
let col = _tbl.options.columns[i];
for (k in kv) {
if (!kv.hasOwnProperty(k))
continue;
@ -535,17 +540,17 @@ $tp.create_table = function (options) {
if (_.contains(col.fields, k)) {
var _cell = $('#' + _tbl.dom_id + ' td[data-cell-id="' + row_id + '-' + i + '"]');
let _cell = $('#' + _tbl.dom_id + ' td[data-cell-id="' + row_id + '-' + i + '"]');
if (col.recreate) {
if (_.isFunction(_tbl.options.on_cell_created)) {
var node = '';
let node = '';
if (_.isUndefined(col.render)) {
node += _row_data[col.key];
} else {
if (_.isFunction(_tbl.render[col.render])) {
var _args = {};
for (var f in col.fields) {
let _args = {};
for (let f in col.fields) {
if (col.fields.hasOwnProperty(f))
_args[f] = _row_data[col.fields[f]];
}
@ -579,13 +584,13 @@ $tp.create_table = function (options) {
// 参数pos_row_id: 0=插入到第一行,-1=插入到最后一行(默认),其他=插入到指定row_id的行之后如果没有找到指定的行则插入到最后
_tbl.add_row = function (rows, pos_row_id, fn_is_duplicated) {
var ret_row_id = [];
var _fn = _.isFunction(fn_is_duplicated) ? fn_is_duplicated : null;
var _new_count = rows.length;
for (var i = 0; i < _new_count; ++i) {
var _my_count = _tbl.row_data.length;
var _is_duplicated = false;
for (var j = 0; j < _my_count; ++j) {
let ret_row_id = [];
let _fn = _.isFunction(fn_is_duplicated) ? fn_is_duplicated : null;
let _new_count = rows.length;
for (let i = 0; i < _new_count; ++i) {
let _my_count = _tbl.row_data.length;
let _is_duplicated = false;
for (let j = 0; j < _my_count; ++j) {
if (_fn) {
if (_fn(rows[i], _tbl.row_data[j])) {
_is_duplicated = true;
@ -617,8 +622,8 @@ $tp.create_table = function (options) {
};
_tbl.remove_row = function (row_id) {
var _index = -1;
for (var i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
let _index = -1;
for (let i = 0, cnt = _tbl.row_data.length; i < cnt; ++i) {
if (_tbl.row_data[i]['_row_id'] === row_id) {
_index = i;
break;
@ -637,7 +642,7 @@ $tp.create_table = function (options) {
_tbl.clear = function () {
$('#' + _tbl.dom_id + ' tbody').empty();
_tbl.row_data = [];
var cb_stack = CALLBACK_STACK.create();
let cb_stack = CALLBACK_STACK.create();
cb_stack
.add(_tbl.on_data_loaded)
.add(_tbl.update_paging)
@ -649,7 +654,7 @@ $tp.create_table = function (options) {
};
_tbl.load_begin = function (delay_) {
var _delay = delay_ || 1000;
let _delay = delay_ || 1000;
_tbl.show_loading(_delay);
};
@ -663,7 +668,7 @@ $tp.create_table = function (options) {
};
_tbl.show_loading = function (delay_) {
var _delay = delay_ || 0;
let _delay = delay_ || 0;
if (_delay > 0) {
if (_tbl.loading_timer === null) {
_tbl.loading_timer = setTimeout(function () {
@ -673,7 +678,7 @@ $tp.create_table = function (options) {
}
}
var msg_loading = '<tr role="row"><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;"><i class="fa fa-circle-o-notch fa-spin"></i> 加载中,请稍候...</td></tr>';
let msg_loading = '<tr role="row"><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;"><i class="fa fa-circle-o-notch fa-spin"></i> 加载中,请稍候...</td></tr>';
$('#' + _tbl.dom_id + ' tbody').prepend($(msg_loading))
};
@ -683,7 +688,7 @@ $tp.create_table = function (options) {
_tbl.loading_timer = null;
}
var msg_loading = '<tr><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;background-color:#f0d4d2;"><i class="fas fa-exclamation-triangle fa-fw"></i> 糟糕!加载失败了...</td></tr>';
let msg_loading = '<tr><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;background-color:#f0d4d2;"><i class="fas fa-exclamation-triangle fa-fw"></i> 糟糕!加载失败了...</td></tr>';
$('#' + _tbl.dom_id + ' tbody').empty().append($(msg_loading))
};
@ -693,11 +698,11 @@ $tp.create_table = function (options) {
_tbl.loading_timer = null;
}
// var msg = '哇哦,没有数据哦...';
// let msg = '哇哦,没有数据哦...';
// if(_tbl.options.message_no_data)
var msg = _tbl.options.message_no_data || '哇哦,没有数据哦...';
let msg = _tbl.options.message_no_data || '哇哦,没有数据哦...';
var msg_loading = '<tr><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;"><i class="fa fa-info-circle fa-fw"></i> ' + msg + '</td></tr>';
let msg_loading = '<tr><td class="loading" colspan="' + _tbl.column_count + '" style="text-align:center;"><i class="fa fa-info-circle fa-fw"></i> ' + msg + '</td></tr>';
$('#' + _tbl.dom_id + ' tbody').empty().append($(msg_loading))
};
@ -728,7 +733,7 @@ $tp.create_table = function (options) {
// TODO: to create fixed header (not scroll), see https://github.com/markmalek/Fixed-Header-Table
$tp.create_table_header = function (tbl, on_created) {
var _tbl_header = {};
let _tbl_header = {};
_tbl_header.dom_id = tbl.dom_id;
_tbl_header._table_ctrl = tbl;
@ -752,9 +757,9 @@ $tp.create_table_header = function (tbl, on_created) {
_tbl_header.order_by = '';
}
var _first_sort = '';
var _sort_asc = true;
var _found = false;
let _first_sort = '';
let _sort_asc = true;
let _found = false;
$.each(_tbl_header._columns, function (i, col) {
if (col.sort) {
if (_first_sort === '') {
@ -778,10 +783,10 @@ $tp.create_table_header = function (tbl, on_created) {
_tbl_header.order_asc = _sort_asc;
// 创建表格头
var _dom = ['<thead><tr>'];
let _dom = ['<thead><tr>'];
$.each(_tbl_header._columns, function (i, col) {
_dom.push('<th');
var _style = '';
let _style = '';
if (col.header_align !== 'center') {
_style += 'text-align:' + col.header_align + ';';
}
@ -793,7 +798,7 @@ $tp.create_table_header = function (tbl, on_created) {
_dom.push('>');
var _title = ['<span data-col-key="' + col.key + '"'];
let _title = ['<span data-col-key="' + col.key + '"'];
if (col.sort) {
_title.push(' class="');
if (_tbl_header.order_by === col.key) {
@ -842,13 +847,13 @@ $tp.create_table_header = function (tbl, on_created) {
};
_tbl_header.click_header = function () {
var t = $(this).attr('data-col-key');
let t = $(this).attr('data-col-key');
_tbl_header.on_head_click(t);
};
// 点击表格分栏,默认操作为按此栏进行升序/降序排序
_tbl_header.on_head_click = function (col_key) {
var i = 0;
let i = 0;
if (col_key === _tbl_header.order_by) {
if (_tbl_header.order_asc) {
@ -861,12 +866,12 @@ $tp.create_table_header = function (tbl, on_created) {
$('#' + _tbl_header.dom_id + ' th .sorting_asc').removeClass('sorting_asc').addClass('sorting');
$('#' + _tbl_header.dom_id + ' th .sorting_desc').removeClass('sorting_desc').addClass('sorting');
var sort_obj = $('#' + _tbl_header.dom_id + " [data-col-key='" + col_key + "']");
let sort_obj = $('#' + _tbl_header.dom_id + " [data-col-key='" + col_key + "']");
sort_obj.removeClass('sorting').addClass('sorting_asc');
_tbl_header.order_by = col_key;
var order_asc = true;
let order_asc = true;
for (i = 0; i < _tbl_header._table_ctrl.column_count; ++i) {
if (_tbl_header._table_ctrl.options.columns[i].key === col_key) {
@ -884,14 +889,14 @@ $tp.create_table_header = function (tbl, on_created) {
_tbl_header.order_asc = order_asc;
}
var cb_stack = CALLBACK_STACK.create();
let cb_stack = CALLBACK_STACK.create();
if (_tbl_header._table_ctrl.options.sort === 'local') {
console.log('sort-by:', col_key);
var data = _.sortBy(_tbl_header._table_ctrl.row_data, col_key);
let data = _.sortBy(_tbl_header._table_ctrl.row_data, col_key);
if (_tbl_header.order_asc) {
_tbl_header._table_ctrl.set_data(cb_stack, {}, {data: data});
} else {
var tmp = [];
let tmp = [];
for (i = data.length - 1; i >= 0; --i) {
tmp.push(data[i]);
}
@ -910,7 +915,7 @@ $tp.create_table_header = function (tbl, on_created) {
$tp.create_table_render = function (tbl, on_created) {
// console.log('create_table_render', tbl, on_created);
var _tbl_render = {};
let _tbl_render = {};
_tbl_render.fs_size = function (row_id, fields) {
if (fields.type === 0 || fields.type === 2)
@ -931,7 +936,7 @@ $tp.create_table_render = function (tbl, on_created) {
};
_tbl_render.host_id = function (row_id, fields) {
var ret = '';
let ret = '';
ret = '<span class="host-id">' + fields.id + '</span>';
ret += '<span class="host-desc">' + fields.desc + '</span>';
return ret;
@ -980,7 +985,7 @@ $tp.create_table_render = function (tbl, on_created) {
};
$tp.create_table_paging = function (tbl, dom_id, options) {
var _tblp = {};
let _tblp = {};
_tblp._table_ctrl = tbl;
tbl.paging_ctrl = _tblp;
_tblp.dom_id = dom_id;
@ -1000,8 +1005,8 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
};
_tblp.init = function (cb_stack) {
var _def_per_page = -1;
var _per_page = -1;
let _def_per_page = -1;
let _per_page = -1;
$.each(_tblp.options.paging_selector.selections, function (i, s) {
if (s.name === _tblp.options.paging_selector.default_select)
_def_per_page = s.val;
@ -1015,7 +1020,7 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
//------------------------------------------------
// create DOM
//------------------------------------------------
var dom = [];
let dom = [];
dom.push('<li><i class="fa fa-list fa-fw"></i> 记录总数 <span data-field="recorder_total">0</span></li>');
dom.push('<li>页数 <span data-field="page_current">1</span>/<span data-field="page_total">0</span></li>');
dom.push('<li data-field="jump">跳转到第 <input data-field="jump-to-page" type="text" class="form-control form-control-sm" style="display:inline-block;width:3em;padding:1px 5px;" /> 页</li>');
@ -1032,7 +1037,7 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
// 绑定事件(输入页码跳转)
$('#' + _tblp.dom_id + ' [data-field="jump-to-page"]').keydown(function (event) {
if (event.which === 13) {
var _val = parseInt($(this).val());
let _val = parseInt($(this).val());
if (_val === _tblp.page_current)
return;
@ -1042,12 +1047,12 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
// 绑定事件(选择每页显示的记录数)
$('#' + _tblp.dom_id + ' li a[data-tp-selector]').click(function () {
var select = parseInt($(this).attr('data-tp-selector'));
let select = parseInt($(this).attr('data-tp-selector'));
if (_tblp.per_page === select)
return;
_tblp.per_page = select;
var name = '';
let name = '';
$.each(_tblp.options.paging_selector.selections, function (i, p) {
if (p.val === select) {
name = p.name;
@ -1074,9 +1079,9 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
};
_tblp.update = function (cb_stack) {
var _total = _tblp._table_ctrl.total || 0;
var _page_index = _tblp._table_ctrl.page_index || 0;
var _page_total = _tblp._table_ctrl.page_total || 0;
let _total = _tblp._table_ctrl.total || 0;
let _page_index = _tblp._table_ctrl.page_index || 0;
let _page_total = _tblp._table_ctrl.page_total || 0;
if (_total > 0)
_page_index += 1;
@ -1101,7 +1106,7 @@ $tp.create_table_paging = function (tbl, dom_id, options) {
};
$tp.create_table_pagination = function (tbl, dom_id, options) {
var _tblp = {};
let _tblp = {};
_tblp._table_ctrl = tbl;
tbl.pagination_ctrl = _tblp;
_tblp.dom_id = dom_id;
@ -1114,8 +1119,8 @@ $tp.create_table_pagination = function (tbl, dom_id, options) {
};
_tblp.update = function (cb_stack) {
var _page_index = _tblp._table_ctrl.page_index || 0;
var _page_total = _tblp._table_ctrl.page_total || 0;
let _page_index = _tblp._table_ctrl.page_index || 0;
let _page_total = _tblp._table_ctrl.page_total || 0;
// 如果只有一页,就没必要显示分页跳转器了。
if (_page_total < 2) {
@ -1124,17 +1129,17 @@ $tp.create_table_pagination = function (tbl, dom_id, options) {
return;
}
var node = [];
let node = [];
// 分页显示规则:
// 总页数小于等于9的全部显示
// 总页数大于9的部分显示
// 第一页 上一页 ... x-4 x-3 x-2 x-1 x x+1 x+2 x+3 x+4 ... 下一页 最后一页
var _start = _page_index - 4;
let _start = _page_index - 4;
if (_start < 0)
_start = 0;
var _end = _start + 9;
let _end = _start + 9;
if (_end > _page_total)
_end = _page_total;
@ -1154,7 +1159,7 @@ $tp.create_table_pagination = function (tbl, dom_id, options) {
node.push('<li class="disabled"><span><i class="fa fa-ellipsis-h fa-fw"></i></span></li>');
}
for (var i = _start; i < _end; ++i) {
for (let i = _start; i < _end; ++i) {
if (i === _page_index)
node.push('<li class="disabled"><span><strong>' + (i + 1) + '</strong></span></li>');
else
@ -1184,7 +1189,7 @@ $tp.create_table_pagination = function (tbl, dom_id, options) {
// 事件绑定
$('#' + _tblp.dom_id + " [data-jump-to]").click(function () {
var _page_index = parseInt($(this).attr('data-jump-to'));
let _page_index = parseInt($(this).attr('data-jump-to'));
_tblp._table_ctrl.paging_jump(_page_index);
});
@ -1199,7 +1204,7 @@ $tp.create_table_pagination = function (tbl, dom_id, options) {
//==============================================================
$tp.create_table_filter_fixed_value = function (tbl, key_value_map) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.name = _.uniqueId('tbl_kv_filter_');
_tblf.kvs = key_value_map;
@ -1212,7 +1217,7 @@ $tp.create_table_filter_fixed_value = function (tbl, key_value_map) {
};
$tp.create_table_header_filter_search = function (tbl, options) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.options = options;
@ -1229,8 +1234,8 @@ $tp.create_table_header_filter_search = function (tbl, options) {
};
_tblf.get_filter = function () {
var _ret = {};
var _val = $('#' + _tblf.dom_id).val();
let _ret = {};
let _val = $('#' + _tblf.dom_id).val();
if (_.isUndefined(_val) || _val.length === 0)
return _ret;
@ -1244,7 +1249,7 @@ $tp.create_table_header_filter_search = function (tbl, options) {
};
_tblf.render = function () {
var _ret = [];
let _ret = [];
_ret.push('<div class="search-input"><div class="input-group">');
_ret.push('<span class="input-group-addon"><i class="fa fa-search fa-fw"></i></span>');
_ret.push('<input id="' + _tblf.dom_id + '" type="text" class="form-control" placeholder="' + _tblf.options.place_holder + '">');
@ -1256,7 +1261,7 @@ $tp.create_table_header_filter_search = function (tbl, options) {
_tblf.on_created = function () {
$('#' + _tblf.dom_id).keydown(function (event) {
if (event.which === 13) {
var _val = $(this).val();
let _val = $(this).val();
if (_val === _tblf.filter_value)
return;
@ -1268,7 +1273,7 @@ $tp.create_table_header_filter_search = function (tbl, options) {
};
$tp.create_table_filter_role = function (tbl, roles) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.dom_id = tbl.dom_id + '-filter-role';
_tblf.name = 'role';
@ -1289,13 +1294,13 @@ $tp.create_table_filter_role = function (tbl, roles) {
_tblf.reset = function (cb_stack) {
_tblf.filter_value = _tblf.default_value;
var name = _tblf._id2name(_tblf.filter_value);
let name = _tblf._id2name(_tblf.filter_value);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
cb_stack.exec();
};
_tblf.render = function () {
var _ret = [];
let _ret = [];
_ret.push('<div id="' + _tblf.dom_id + '" class="btn-group search-select">');
_ret.push('<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">');
_ret.push('<span data-tp-select-result></span> <i class="fa fa-caret-right"></i></button>');
@ -1317,7 +1322,7 @@ $tp.create_table_filter_role = function (tbl, roles) {
return '所有';
if (id_ === 0)
return '尚未设置';
for (var i = 0; i < _tblf.roles.length; ++i) {
for (let i = 0; i < _tblf.roles.length; ++i) {
if (_tblf.roles[i].id === id_)
return _tblf.roles[i].name;
}
@ -1328,12 +1333,12 @@ $tp.create_table_filter_role = function (tbl, roles) {
_tblf.on_created = function () {
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text('所有');
$('#' + _tblf.dom_id + ' li a[data-tp-selector]').click(function () {
var select = parseInt($(this).attr('data-tp-selector'));
let select = parseInt($(this).attr('data-tp-selector'));
if (_tblf.filter_value === select)
return;
_tblf.filter_value = select;
var name = _tblf._id2name(select);
let name = _tblf._id2name(select);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
// 刷新数据
@ -1343,7 +1348,7 @@ $tp.create_table_filter_role = function (tbl, roles) {
};
// $tp.create_table_filter_user_state = function (tbl, states, on_created) {
// var _tblf = {};
// let _tblf = {};
// _tblf._table_ctrl = tbl;
// _tblf.dom_id = tbl.dom_id + '-filter-user-state';
// _tblf.name = 'user_state';
@ -1364,13 +1369,13 @@ $tp.create_table_filter_role = function (tbl, roles) {
//
// _tblf.reset = function (cb_stack) {
// _tblf.filter_value = _tblf.default_value;
// var name = _tblf._id2name(_tblf.filter_value);
// let name = _tblf._id2name(_tblf.filter_value);
// $('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
// cb_stack.exec();
// };
//
// _tblf.render = function () {
// var _ret = [];
// let _ret = [];
// _ret.push('<div id="' + _tblf.dom_id + '" class="btn-group search-select" role="group">');
// _ret.push('<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">');
// _ret.push('<span data-tp-select-result></span> <i class="fa fa-caret-right"></i></button>');
@ -1388,7 +1393,7 @@ $tp.create_table_filter_role = function (tbl, roles) {
// _tblf._id2name = function (id_) {
// if (id_ === 0)
// return '所有';
// for (var i = 0; i < _tblf.states.length; ++i) {
// for (let i = 0; i < _tblf.states.length; ++i) {
// if (_tblf.states[i].id === id_)
// return _tblf.states[i].name;
// }
@ -1399,12 +1404,12 @@ $tp.create_table_filter_role = function (tbl, roles) {
// _tblf.on_created = function () {
// $('#' + _tblf.dom_id + ' span[data-tp-select-result]').text('所有');
// $('#' + _tblf.dom_id + ' li a[data-tp-selector]').click(function () {
// var select = parseInt($(this).attr('data-tp-selector'));
// let select = parseInt($(this).attr('data-tp-selector'));
// if (_tblf.filter_value === select)
// return;
// _tblf.filter_value = select;
//
// var name = _tblf._id2name(select);
// let name = _tblf._id2name(select);
// // console.log(select, name);
//
// $('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
@ -1417,7 +1422,7 @@ $tp.create_table_filter_role = function (tbl, roles) {
// };
$tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.dom_id = tbl.dom_id + '-header-filter-' + name;
_tblf.name = name;
@ -1426,7 +1431,7 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
_tblf.states = [];
if (exclude_ids && exclude_ids.length > 0) {
for (var i = 0; i < states.length; ++i) {
for (let i = 0; i < states.length; ++i) {
if (_.indexOf(exclude_ids, states[i].id) !== -1)
continue;
_tblf.states.push(states[i]);
@ -1443,7 +1448,7 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
};
_tblf.get_filter = function () {
var ret = {};
let ret = {};
if (_tblf.default_value === _tblf.filter_value)
return ret;
ret[_tblf.name] = _tblf.filter_value;
@ -1452,13 +1457,13 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
_tblf.reset = function (cb_stack) {
_tblf.filter_value = _tblf.default_value;
var name = _tblf._id2name(_tblf.filter_value);
let name = _tblf._id2name(_tblf.filter_value);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
cb_stack.exec();
};
_tblf.render = function () {
var _ret = [];
let _ret = [];
_ret.push('<div id="' + _tblf.dom_id + '" class="btn-group search-select" role="group">');
_ret.push('<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">');
_ret.push('<span data-tp-select-result></span> <i class="fa fa-caret-right"></i></button>');
@ -1476,7 +1481,7 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
_tblf._id2name = function (id_) {
if (id_ === 0)
return '所有';
for (var i = 0; i < _tblf.states.length; ++i) {
for (let i = 0; i < _tblf.states.length; ++i) {
if (_tblf.states[i].id === id_)
return _tblf.states[i].name;
}
@ -1487,12 +1492,12 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
_tblf.on_created = function () {
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text('所有');
$('#' + _tblf.dom_id + ' li a[data-tp-selector]').click(function () {
var select = parseInt($(this).attr('data-tp-selector'));
let select = parseInt($(this).attr('data-tp-selector'));
if (_tblf.filter_value === select)
return;
_tblf.filter_value = select;
var name = _tblf._id2name(select);
let name = _tblf._id2name(select);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
@ -1503,7 +1508,7 @@ $tp.create_table_header_filter_state = function (tbl, name, states, exclude_ids)
};
$tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_ids) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.dom_id = tbl.dom_id + '-header-filter-' + name;
_tblf.name = name;
@ -1512,7 +1517,7 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
_tblf.states = [];
if (exclude_ids && exclude_ids.length > 0) {
for (var i = 0; i < states.length; ++i) {
for (let i = 0; i < states.length; ++i) {
if (_.indexOf(exclude_ids, states[i].id) !== -1)
continue;
_tblf.states.push(states[i]);
@ -1529,7 +1534,7 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
};
_tblf.get_filter = function () {
var ret = {};
let ret = {};
if (_tblf.default_value === _tblf.filter_value)
return ret;
ret[_tblf.name] = _tblf.filter_value;
@ -1538,13 +1543,13 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
_tblf.reset = function (cb_stack) {
_tblf.filter_value = _tblf.default_value;
var name = _tblf._id2name(_tblf.filter_value);
let name = _tblf._id2name(_tblf.filter_value);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
cb_stack.exec();
};
_tblf.render = function () {
var _ret = [];
let _ret = [];
_ret.push('<div id="' + _tblf.dom_id + '" class="btn-group search-select" role="group">');
_ret.push('<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">');
_ret.push('<span data-tp-select-result></span> <i class="fa fa-caret-right"></i></button>');
@ -1562,7 +1567,7 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
_tblf._id2name = function (id_) {
if (id_ === 0)
return '所有';
for (var i = 0; i < _tblf.states.length; ++i) {
for (let i = 0; i < _tblf.states.length; ++i) {
if (_tblf.states[i].id === id_)
return _tblf.states[i].name;
}
@ -1574,12 +1579,12 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text('所有');
$('#' + _tblf.dom_id + ' li a[data-tp-selector]').click(function () {
var select = parseInt($(this).attr('data-tp-selector'));
let select = parseInt($(this).attr('data-tp-selector'));
if (_tblf.filter_value === select)
return;
_tblf.filter_value = select;
var name = _tblf._id2name(select);
let name = _tblf._id2name(select);
$('#' + _tblf.dom_id + ' span[data-tp-select-result]').text(name);
@ -1590,7 +1595,7 @@ $tp.create_table_header_filter_dropdown = function (tbl, name, states, exclude_i
};
$tp.create_table_filter_group = function (tbl, name, dom_id, groups) {
var _tblf = {};
let _tblf = {};
_tblf._table_ctrl = tbl;
_tblf.dom_id = dom_id;
_tblf.name = name;
@ -1601,7 +1606,7 @@ $tp.create_table_filter_group = function (tbl, name, dom_id, groups) {
_tblf._table_ctrl.add_filter_ctrl(_tblf.name, _tblf);
_tblf.init = function (cb_stack) {
var html = [];
let html = [];
html.push('<li><a href="javascript:;" data-tp-selector="-1" data-name="所有"><i class="fa fa-caret-right fa-fw"></i> 所有</a></li>');
$.each(_tblf.groups, function (i, item) {
html.push('<li><a href="javascript:;" data-tp-selector="' + item.id + '" data-name="' + item.name + '"><i class="fa fa-caret-right fa-fw"></i> ' + item.name + '</a></li>');
@ -1610,12 +1615,12 @@ $tp.create_table_filter_group = function (tbl, name, dom_id, groups) {
$(_tblf.dom_id + ' li a[data-tp-selector]').click(function () {
var select = parseInt($(this).attr('data-tp-selector'));
let select = parseInt($(this).attr('data-tp-selector'));
if (_tblf.filter_value === select)
return;
_tblf.filter_value = select;
var name = _tblf._id2name(select);
let name = _tblf._id2name(select);
$(_tblf.dom_id + ' span[data-tp-select-result]').text(name);
// 刷新数据
@ -1627,7 +1632,7 @@ $tp.create_table_filter_group = function (tbl, name, dom_id, groups) {
};
_tblf.get_filter = function () {
var ret = {};
let ret = {};
ret[_tblf.name] = _tblf.filter_value;
return ret;
};
@ -1637,7 +1642,7 @@ $tp.create_table_filter_group = function (tbl, name, dom_id, groups) {
return '所有';
// if (id_ === 0)
// return '尚未设置';
for (var i = 0; i < _tblf.groups.length; ++i) {
for (let i = 0; i < _tblf.groups.length; ++i) {
if (_tblf.groups[i].id === id_)
return _tblf.groups[i].name;
}

View File

@ -28,7 +28,6 @@
<div id="steps-detail" class="steps-detail"></div>
<div><p id="message" class="op_box" style="display:none;"></p></div>
<div id="step2" style="display:none;">
<hr/>
<h2><i class="fa fa-chevron-right"></i> 已完成!</h2>

File diff suppressed because it is too large Load Diff

View File

@ -283,16 +283,11 @@
<div class="modal-footer">
<div class="row">
<div class="col-sm-8">
<div id="edit-user-message" class="alert alert-danger"
style="text-align:left;display:none;"></div>
<div id="edit-user-message" class="alert alert-danger" style="text-align:left;display:none;"></div>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-sm btn-primary" id="btn-edit-user-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-times fa-fw"></i> 取消
</button>
<button type="button" class="btn btn-sm btn-primary" id="btn-edit-user-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-times fa-fw"></i> 取消</button>
</div>
</div>
</div>
@ -711,9 +706,7 @@
<div class="modal-footer">
<div class="row">
<div class="col-sm-12" style="text-align:right;">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal">
<i class="fa fa-times fa-fw"></i> 关闭
</button>
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-times fa-fw"></i> 关闭</button>
</div>
</div>
</div>

View File

@ -172,7 +172,7 @@ class BaseAppConfig(dict):
os.rename(tmp_file, cfg_file)
return True
except Exception as e:
print(e.__str__())
log.e('{}\n'.format(e.__str__()))
return False
def _update_kvs(self, section, key, val):
@ -223,7 +223,7 @@ class BaseAppConfig(dict):
try:
return int(self['_kvs'][_sec][_key]), True
except ValueError as e:
print(e.__str__())
log.e('{}\n'.format(e.__str__()))
return def_value, False
def get_bool(self, key, def_value=False):

View File

@ -33,6 +33,7 @@ class DatabaseInit:
self._create_syslog()
self._create_record()
self._create_record_audit()
self._create_integration_auth()
self._make_builtin_data(sysadmin, email, password)
except:
log.e('[db] can not create and initialize database.\n')
@ -825,6 +826,32 @@ class DatabaseInit:
'CREATE TABLE `{}record_audit` ({});'.format(self.db.table_prefix, ','.join(f))
)
def _create_integration_auth(self):
""" 第三方服务集成认证信息 """
f = list()
# id: 自增主键
f.append('`id` integer PRIMARY KEY {}'.format(self.db.auto_increment))
# acc_key: 访问KEY
f.append('`acc_key` varchar(32) DEFAULT ""')
# acc_sec: 访问密钥
f.append('`acc_sec` varchar(64) DEFAULT ""')
# role_id: 此访问授权对应的角色ID, 关联到role表也即对应的权限
f.append('`role_id` int(11) DEFAULT 0')
# name: 第三方服务名称
f.append('`name` varchar(64) DEFAULT ""')
# comment: 描述
f.append('`comment` varchar(64) DEFAULT ""')
# creator_id: 创建者的id0=系统默认创建
f.append('`creator_id` int(11) DEFAULT 0')
# create_time: 创建时间 timestamp
f.append('`create_time` int(11) DEFAULT 0')
self._db_exec(
'创建第三方服务集成认证信息表...',
'CREATE TABLE `{}integration_auth` ({});'.format(self.db.table_prefix, ','.join(f))
)
def _make_builtin_data(self, sysadmin, email, password):
_time_now = tp_timestamp_sec()

View File

@ -221,3 +221,64 @@ class DatabaseUpgrade:
' - 创建核心服务器表...',
'CREATE TABLE `{}core_server` ({});'.format(self.db.table_prefix, ','.join(f))
)
def _upgrade_to_v8(self):
_step = self.step_begin('准备升级到数据库版本 v8...')
self.step_end(_step, 0, '')
try:
# 1. 创建缺失的 integration_auth 表
_step = self.step_begin(' - 检查 integration_auth 数据表...')
ret = self.db.is_table_exists('{}integration_auth'.format(self.db.table_prefix))
if ret is None:
self.step_end(_step, -1, '无法连接到数据库')
return False
elif not ret:
_step = self.step_begin(' - 创建数据表 integration_auth...')
self._v8_integration_auth()
self.step_end(_step, 0)
_step = self.step_begin(' - 更新数据库版本号...')
if not self.db.exec('UPDATE `{}config` SET `value`="8" WHERE `name`="db_ver";'.format(self.db.table_prefix)):
self.step_end(_step, -1, '无法更新数据库版本号')
return False
self.step_end(_step, 0)
_step = self.step_begin('升级到 v8 完成')
self.step_end(_step, 0)
return True
except:
log.e('failed.\n')
self.step_end(_step, -1)
return False
def _v8_integration_auth(self):
""" 第三方服务集成认证信息
v8 新增
"""
f = list()
# id: 自增主键
f.append('`id` integer PRIMARY KEY {}'.format(self.db.auto_increment))
# acc_key: 访问KEY
f.append('`acc_key` varchar(32) DEFAULT ""')
# acc_sec: 访问密钥
f.append('`acc_sec` varchar(64) DEFAULT ""')
# role_id: 此访问授权对应的角色ID, 关联到role表也即对应的权限
f.append('`role_id` int(11) DEFAULT 0')
# name: 第三方服务名称
f.append('`name` varchar(64) DEFAULT ""')
# comment: 描述
f.append('`comment` varchar(64) DEFAULT ""')
# creator_id: 创建者的id0=系统默认创建
f.append('`creator_id` int(11) DEFAULT 0')
# create_time: 创建时间 timestamp
f.append('`create_time` int(11) DEFAULT 0')
self._db_exec(
' - 创建第三方服务集成认证信息表...',
'CREATE TABLE `{}integration_auth` ({});'.format(self.db.table_prefix, ','.join(f))
)

View File

@ -25,7 +25,8 @@ __all__ = ['get_db', 'SQL']
class TPDatabase:
# 注意,每次调整数据库结构,必须增加版本号,并且在升级接口中编写对应的升级操作
# 20190123: server-v3.2.2, db-v7
DB_VERSION = 7
# 20220526: server-v3.6.3, db-v8
DB_VERSION = 8
DB_TYPE_UNKNOWN = 0
DB_TYPE_SQLITE = 1

View File

@ -267,6 +267,12 @@ controllers = [
(r'/system/do-ldap-import', system.DoLdapImportHandler),
# - [text] 导出数据库
(r'/system/export-db', system.DoExportDBHandler),
# - [json] 获取第三方服务集成使用的密钥列表
(r'/system/get-integration', system.DoGetIntegrationHandler),
# - [json] 创建/更新第三方服务集成使用的密钥
(r'/system/update-integration', system.DoUpdateIntegrationHandler),
# - [json] 移除第三方服务集成使用的密钥
(r'/system/remove-integration', system.DoRemoveIntegrationHandler),
#
# - [json] 获取服务器时间

View File

@ -23,7 +23,7 @@ from app.model import user
from app.base.core_server import core_service_async_post_http
from app.base.session import tp_session
from app.logic.auth.ldap import Ldap
from app.base.utils import tp_timestamp_sec
from app.base.utils import tp_timestamp_sec, tp_gen_password
from ._sidebar_menu import tp_generate_sidebar
@ -679,7 +679,6 @@ class DoLdapImportHandler(TPBaseJsonHandler):
user_list.append(u)
print(user_list)
user.create_users(self, user_list, success, failed)
# 对于创建成功的用户,发送密码邮件函
@ -770,3 +769,83 @@ class DoRebuildAuditAuzMapHandler(TPBaseJsonHandler):
err = ops.build_auz_map()
self.write_json(err)
class DoGetIntegrationHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
err, total_count, page_index, row_data = system_model.get_integration(with_acc_sec=False)
ret = dict()
ret['page_index'] = page_index
ret['total'] = total_count
ret['data'] = row_data
self.write_json(err, data=ret)
class DoUpdateIntegrationHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
_id = int(args['id'])
_role_id = int(args['role_id'])
_name = args['name']
_comment = args['comment']
if _id != -1:
_acc_key = args['acc_key']
_regenerate = args['regenerate']
except:
return self.write_json(TPE_PARAM)
ret = dict()
if _id == -1:
err, acc_key, acc_sec = system_model.create_integration(self, _role_id, _name, _comment)
else:
err, acc_key, acc_sec = system_model.update_integration(self, _id, _role_id, _name, _comment, _acc_key, _regenerate)
if err == TPE_OK:
ret['acc_key'] = acc_key
ret['acc_sec'] = acc_sec
self.write_json(TPE_OK, data=ret)
else:
self.write_json(err)
class DoRemoveIntegrationHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
items = args['items']
except:
return self.write_json(TPE_PARAM)
err = system_model.remove_integration(self, items)
self.write_json(err)

View File

@ -13,7 +13,7 @@ from app.const import *
class DashboardHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin): # 针对websocket处理类重写同源检查的方法
print('ws-dashboard origin:', origin)
# print('ws-dashboard origin:', origin)
return True
# 接受websocket链接保存链接实例

View File

@ -4,7 +4,7 @@ import json
from app.const import *
from app.base.db import get_db, SQL
from app.base.logger import log
from app.base.utils import tp_timestamp_sec
from app.base.utils import tp_timestamp_sec, tp_gen_password
from . import syslog
@ -52,13 +52,12 @@ def add_role(handler, role_name, privilege):
_id = db.last_insert_id()
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "创建角色:{}".format(role_name))
return TPE_OK, _id
def update_role(handler, role_id, role_name, privilege):
"""
更新一个远程账号
更新角色
"""
db = get_db()
@ -75,6 +74,8 @@ def update_role(handler, role_id, role_name, privilege):
if not db_ret:
return TPE_DATABASE
operator = handler.get_current_user()
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "更新角色:{}".format(role_name))
return TPE_OK
@ -108,3 +109,105 @@ def remove_role(handler, role_id):
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "删除角色:{}".format(role_name))
return TPE_OK
def get_integration(with_acc_sec=False):
s = SQL(get_db())
fields = ['id', 'acc_key', 'name', 'comment']
if with_acc_sec:
fields.append('acc_sec')
s.select_from('integration_auth', fields, alt_name='ia')
s.left_join('role', ['id', 'name', 'privilege'], join_on='r.id=ia.role_id', alt_name='r', out_map={'id': 'role_id', 'name': 'role_name'})
s.order_by('ia.name', True)
err = s.query()
return err, s.total_count, s.page_index, s.recorder
def create_integration(handler, role_id, name, comment):
db = get_db()
_time_now = tp_timestamp_sec()
operator = handler.get_current_user()
# 1. 随机生成一个access-key并判断是否已经存在了
acc_key = ''
acc_sec = tp_gen_password(32)
for i in range(20):
_acc_key = 'TP{}'.format(tp_gen_password(14))
sql = 'SELECT `id` FROM {dbtp}integration_auth WHERE `acc_key`="{acc_key}";'.format(dbtp=db.table_prefix, acc_key=_acc_key)
db_ret = db.query(sql)
if db_ret is not None and len(db_ret) > 0:
continue
acc_key = _acc_key
break
if len(acc_key) == 0:
return TPE_FAILED, None, None
sql = 'INSERT INTO `{dbtp}integration_auth` (`acc_key`, `acc_sec`, `role_id`, `name`, `comment`, `creator_id`, `create_time`) VALUES ' \
'("{acc_key}", "{acc_sec}", {role_id}, "{name}", "{comment}", {creator_id}, {create_time});' \
''.format(dbtp=db.table_prefix, acc_key=acc_key, acc_sec=acc_sec, role_id=role_id, name=name, comment=comment, creator_id=operator['id'], create_time=_time_now)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE, None, None
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "创建外部密钥 {}".format(name))
return TPE_OK, acc_key, acc_sec
def update_integration(handler, _id, role_id, name, comment, acc_key, regenerate):
db = get_db()
_time_now = tp_timestamp_sec()
operator = handler.get_current_user()
acc_sec = None
# 1. 检查 id, access-key 是否存在
sql = 'SELECT `id` FROM {dbtp}integration_auth WHERE `id`={ph} AND `acc_key`={ph};'.format(dbtp=db.table_prefix, ph=db.place_holder)
db_ret = db.query(sql, (_id, acc_key))
if db_ret is None or len(db_ret) == 0:
return TPE_NOT_EXISTS, None, None
if regenerate:
acc_sec = tp_gen_password(32)
sql = 'UPDATE `{dbtp}integration_auth` SET `name`={ph}, `comment`={ph}, `role_id`={ph}, `acc_sec`={ph} WHERE `id`={ph};' \
''.format(dbtp=db.table_prefix, ph=db.place_holder)
db_ret = db.exec(sql, (name, comment, role_id, acc_sec, _id,))
else:
sql = 'UPDATE `{dbtp}integration_auth` SET `name`={ph}, `comment`={ph}, `role_id`={ph} WHERE `id`={ph};' \
''.format(dbtp=db.table_prefix, ph=db.place_holder)
db_ret = db.exec(sql, (name, comment, role_id, _id,))
if not db_ret:
return TPE_DATABASE, None, None
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "更新外部密钥 {}{}".format(name, '重新生成access-secret。' if regenerate else ''))
return TPE_OK, acc_key, acc_sec
def remove_integration(handler, items):
item_ids = ','.join([str(i) for i in items])
# 1. 获取名称,用于记录系统日志
where = 'i.id IN ({ids})'.format(ids=item_ids)
db = get_db()
s = SQL(db)
err = s.select_from('integration_auth', ['name'], alt_name='i').where(where).query()
if err != TPE_OK:
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
name_list = [n['name'] for n in s.recorder]
# 删除
sql = 'DELETE FROM `{tp}integration_auth` WHERE `id` IN ({ids});'.format(tp=db.table_prefix, ids=item_ids)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
# 记录系统日志
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "删除外部集成密钥:{names}".format(names=''.join(name_list)))
return TPE_OK