support export database.

pull/236/head
Apex Liu 2019-11-27 20:09:11 +08:00
parent f99d39e2fa
commit b4be3de0b3
7 changed files with 131 additions and 22 deletions

View File

@ -706,6 +706,7 @@ $app.create_config_storage = function () {
storage_size: $('#storage-size'), storage_size: $('#storage-size'),
btn_save: $('#btn-save-storage-config'), btn_save: $('#btn-save-storage-config'),
btn_cleanup: $('#btn-clear-storage'), btn_cleanup: $('#btn-clear-storage'),
btn_export_db: $('#btn-export-db'),
input_keep_log: $('#storage-keep-log'), input_keep_log: $('#storage-keep-log'),
input_keep_record: $('#storage-keep-record'), input_keep_record: $('#storage-keep-record'),
@ -735,6 +736,10 @@ $app.create_config_storage = function () {
_sto.on_btn_cleanup(); _sto.on_btn_cleanup();
}); });
_sto.dom.btn_export_db.click(function() {
_sto.on_export_db();
});
cb_stack.exec(); cb_stack.exec();
}; };
@ -835,5 +840,9 @@ $app.create_config_storage = function () {
); );
}; };
_sto.on_export_db = function() {
window.location.href = '/system/export-db';
};
return _sto; return _sto;
}; };

View File

@ -378,6 +378,21 @@
<button id="btn-clear-storage" class="btn btn-sm btn-success"><i class="fa fa-leaf fa-fw"></i> 现在立即清理</button> <button id="btn-clear-storage" class="btn btn-sm btn-success"><i class="fa fa-leaf fa-fw"></i> 现在立即清理</button>
</td> </td>
</tr> </tr>
<tr>
<td colspan="2" class="title">
<hr class="hr-sm"/>
数据库导出
</td>
</tr>
<tr>
<td class="key"></td>
<td class="value">
<button id="btn-export-db" class="btn btn-sm btn-success"><i class="fa fa-leaf fa-fw"></i> 导出到SQL</button>
</td>
</tr>
</table> </table>
<hr/> <hr/>
<button id="btn-save-storage-config" class="btn btn-sm btn-primary"><i class="fa fa-check-circle fa-fw"></i> 保存存储设置</button> <button id="btn-save-storage-config" class="btn btn-sm btn-primary"><i class="fa fa-check-circle fa-fw"></i> 保存存储设置</button>

View File

@ -14,22 +14,49 @@ def _db_exec(db, step_begin, step_end, msg, sql):
step_end(_step, 0) step_end(_step, 0)
def _export_table(db, table_name, fields): def _export_table(db, table_name):
table_name = '{}{}'.format(db.table_prefix, table_name)
f = db.get_fields(table_name)
fields = [i[0] for i in f]
types = [i[1] for i in f]
if fields is None:
return '错误:表 {} 不存在'.format(table_name)
s = list()
for t in types:
if (t.lower().find('char') != -1) or (t.lower().find('text') != -1):
s.append(True)
else:
s.append(False)
ret = ['', '-- table: {}'.format(table_name), '-- fields: {}'.format(', '.join(fields)), 'TRUNCATE TABLE `{}`;'.format(table_name)] ret = ['', '-- table: {}'.format(table_name), '-- fields: {}'.format(', '.join(fields)), 'TRUNCATE TABLE `{}`;'.format(table_name)]
fields_str = '`,`'.join(fields) fields_str = '`,`'.join(fields)
sql = 'SELECT `{}` FROM `{}{}`'.format(fields_str, db.table_prefix, table_name) sql = 'SELECT `{}` FROM `{}`'.format(fields_str, table_name)
d = db.query(sql) d = db.query(sql)
if not d or len(d) == 0: if not d or len(d) == 0:
ret.append('-- table is empty.') ret.append('-- table is empty.')
else: else:
fields_count = len(fields) fields_count = len(fields)
for i in range(len(d)): for i in range(len(d)):
x = [] # x = []
# for j in range(fields_count):
# x.append(d[i][j].__str__())
# val = "','".join(x).replace('\n', '\\n')
x = list()
for j in range(fields_count): for j in range(fields_count):
x.append(d[i][j].__str__()) # if j > 0:
val = "','".join(x).replace('\n', '\\n') # x.append(',')
sql = "INSERT INTO `{}` VALUES ('{}');".format(table_name, val) if s[j]:
if d[i][j] is None:
x.append('NULL')
else:
x.append('"{}"'.format(d[i][j].replace(r'"', r'\"')))
else:
x.append('{}'.format(d[i][j]))
val = ','.join(x)
print('VAL:', val, '\n')
sql = "INSERT INTO `{}` VALUES ({});".format(table_name, val)
ret.append(sql) ret.append(sql)
return '\r\n'.join(ret) return '\r\n'.join(ret)
@ -52,21 +79,41 @@ def export_database(db):
else: else:
ret.append('-- DATABASE VERSION {}'.format(db_ret[0][0])) ret.append('-- DATABASE VERSION {}'.format(db_ret[0][0]))
_fields = ['account_id', 'account_type', 'account_name', 'account_pwd', 'account_status', 'account_lock', 'account_desc', 'oath_secret'] # _fields = ['account_id', 'account_type', 'account_name', 'account_pwd', 'account_status', 'account_lock', 'account_desc', 'oath_secret']
ret.append(_export_table(db, 'account', _fields)) # ret.append(_export_table(db, 'account', _fields))
_fields = ['auth_id', 'account_name', 'host_id', 'host_auth_id'] # _fields = ['auth_id', 'account_name', 'host_id', 'host_auth_id']
ret.append(_export_table(db, 'auth', _fields)) # ret.append(_export_table(db, 'auth', _fields))
_fields = ['cert_id', 'cert_name', 'cert_pub', 'cert_pri', 'cert_desc'] # _fields = ['cert_id', 'cert_name', 'cert_pub', 'cert_pri', 'cert_desc']
ret.append(_export_table(db, 'key', _fields)) # ret.append(_export_table(db, 'key', _fields))
_fields = ['name', 'value'] # _fields = ['name', 'value']
ret.append(_export_table(db, 'config', _fields)) # ret.append(_export_table(db, 'config', _fields))
_fields = ['group_id', 'group_name'] # _fields = ['group_id', 'group_name']
ret.append(_export_table(db, 'group', _fields)) # ret.append(_export_table(db, 'group', _fields))
_fields = ['host_id', 'group_id', 'host_sys_type', 'host_ip', 'host_port', 'protocol', 'host_lock', 'host_desc'] # _fields = ['host_id', 'group_id', 'host_sys_type', 'host_ip', 'host_port', 'protocol', 'host_lock', 'host_desc']
ret.append(_export_table(db, 'host_info', _fields)) # ret.append(_export_table(db, 'host_info', _fields))
_fields = ['id', 'host_id', 'auth_mode', 'user_name', 'user_pswd', 'user_param', 'cert_id', 'encrypt', 'log_time'] # _fields = ['id', 'host_id', 'auth_mode', 'user_name', 'user_pswd', 'user_param', 'cert_id', 'encrypt', 'log_time']
ret.append(_export_table(db, 'auth_info', _fields)) # ret.append(_export_table(db, 'auth_info', _fields))
_fields = ['id', 'session_id', 'account_name', 'host_ip', 'host_port', 'sys_type', 'auth_type', 'protocol', 'user_name', 'ret_code', 'begin_time', 'end_time', 'log_time'] # _fields = ['id', 'session_id', 'account_name', 'host_ip', 'host_port', 'sys_type', 'auth_type', 'protocol', 'user_name', 'ret_code', 'begin_time', 'end_time', 'log_time']
ret.append(_export_table(db, 'log', _fields)) # ret.append(_export_table(db, 'log', _fields))
ret.append(_export_table(db, 'config'))
ret.append(_export_table(db, 'core_server'))
ret.append(_export_table(db, 'role'))
ret.append(_export_table(db, 'user'))
ret.append(_export_table(db, 'user_rpt'))
ret.append(_export_table(db, 'host'))
ret.append(_export_table(db, 'acc'))
ret.append(_export_table(db, 'acc_auth'))
ret.append(_export_table(db, 'group'))
ret.append(_export_table(db, 'group_map'))
ret.append(_export_table(db, 'ops_policy'))
ret.append(_export_table(db, 'ops_auz'))
ret.append(_export_table(db, 'ops_map'))
ret.append(_export_table(db, 'audit_policy'))
ret.append(_export_table(db, 'audit_auz'))
ret.append(_export_table(db, 'audit_map'))
ret.append(_export_table(db, 'syslog'))
ret.append(_export_table(db, 'record'))
ret.append(_export_table(db, 'record_audit'))
return '\r\n'.join(ret), True return '\r\n'.join(ret), True

View File

@ -177,6 +177,25 @@ class TPDatabase:
log.e('Unknown database type.\n') log.e('Unknown database type.\n')
return None return None
def get_fields(self, table_name):
fields = list()
if self.db_type == self.DB_TYPE_SQLITE:
ret = self.query('PRAGMA table_info(`{}`);'.format(table_name))
log.d('[sqlite] fields of {}'.format(table_name), ret, '\n')
if ret is None:
return None
for f in ret:
fields.append((f[1], f[2])) # field_name, field_type, e.g.: ('id', 'integer'), ('desc', 'varchar(255)')
elif self.db_type == self.DB_TYPE_MYSQL:
ret = self.query('SELECT `column_name` FROM `information_schema`.`columns` WHERE `table_schema`="db" AND `table_name`="{}";'.format(table_name))
log.d('[mysql] fields of {}'.format(table_name), ret, '\n')
if ret is None:
return None
for f in ret:
fields.append(f)
return fields
def is_field_exists(self, table_name, field_name): def is_field_exists(self, table_name, field_name):
if self.db_type == self.DB_TYPE_SQLITE: if self.db_type == self.DB_TYPE_SQLITE:
ret = self.query('PRAGMA table_info(`{}`);'.format(table_name)) ret = self.query('PRAGMA table_info(`{}`);'.format(table_name))

View File

@ -160,6 +160,10 @@ def tp_second2human(n):
return ret return ret
def tp_timestamp_from_str(t):
return 0
def tp_timestamp_sec(): def tp_timestamp_sec():
return int(datetime.datetime.now().timestamp()) return int(datetime.datetime.now().timestamp())

View File

@ -262,6 +262,8 @@ controllers = [
(r'/system/do-ldap-get-users', system.DoLdapGetUsersHandler), (r'/system/do-ldap-get-users', system.DoLdapGetUsersHandler),
# - [json] 导入LDAP用户 # - [json] 导入LDAP用户
(r'/system/do-ldap-import', system.DoLdapImportHandler), (r'/system/do-ldap-import', system.DoLdapImportHandler),
# - [text] 导出数据库
(r'/system/export-db', system.DoExportDBHandler),
# #
# - [json] 获取服务器时间 # - [json] 获取服务器时间

View File

@ -4,6 +4,7 @@ import datetime
import hashlib import hashlib
import json import json
import shutil import shutil
import time
import app.model.system as system_model import app.model.system as system_model
import tornado.gen import tornado.gen
@ -87,6 +88,18 @@ class RoleHandler(TPBaseHandler):
self.render('system/role.mako') self.render('system/role.mako')
class DoExportDBHandler(TPBaseHandler):
def get(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
sql, err = get_db().export_to_sql()
self.set_header('Content-Type', 'application/sql')
self.set_header('Content-Disposition', 'attachment; filename="teleport-db-export-{}.sql"'.format(time.strftime('%Y%m%d-%H%M%S')))
self.write(sql)
self.finish()
class DoRoleUpdateHandler(TPBaseJsonHandler): class DoRoleUpdateHandler(TPBaseJsonHandler):
@tornado.gen.coroutine @tornado.gen.coroutine
def post(self): def post(self):