mirror of https://github.com/tp4a/teleport
working...
parent
f142793394
commit
054deb839e
|
@ -0,0 +1,2 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from eom_common.eomcore.logger import log
|
||||
from eom_app.app.util import sec_generate_password
|
||||
|
||||
# 升级数据表结构时必须升级此版本号,并编写响应的升级SQL
|
||||
TELEPORT_DATABASE_VERSION = 10
|
||||
|
||||
|
||||
def create_and_init(db, step_begin, step_end):
|
||||
_admin_sec_password = sec_generate_password('admin')
|
||||
|
||||
_step = step_begin('创建表 account')
|
||||
|
||||
ret = db.exec("""CREATE TABLE `{}account` (
|
||||
`account_id` integer PRIMARY KEY AUTOINCREMENT,
|
||||
`account_type` int(11) DEFAULT 0,
|
||||
`account_name` varchar(32) DEFAULT NULL,
|
||||
`account_pwd` varchar(32) DEFAULT NULL,
|
||||
`account_status` int(11) DEFAULT 0,
|
||||
`account_lock` int(11) DEFAULT 0,
|
||||
`account_desc` varchar(255)
|
||||
);""".format(db.table_prefix))
|
||||
if not ret:
|
||||
log.e('create table `account` failed.')
|
||||
step_end(_step, -1)
|
||||
return
|
||||
else:
|
||||
log.i('create table `account` ok.')
|
||||
step_end(_step, 0)
|
|
@ -1,19 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import threading
|
||||
import sqlite3
|
||||
import builtins
|
||||
import os
|
||||
import sqlite3
|
||||
import threading
|
||||
|
||||
from .configs import app_cfg
|
||||
from eom_common.eomcore.logger import log
|
||||
from .configs import app_cfg
|
||||
from .database.create import create_and_init, TELEPORT_DATABASE_VERSION
|
||||
|
||||
cfg = app_cfg()
|
||||
|
||||
__all__ = ['get_db']
|
||||
|
||||
# 注意,每次调整数据库结构,必须增加版本号,并且在升级接口中编写对应的升级操作
|
||||
TELEPORT_DATABASE_VERSION = 2
|
||||
# TELEPORT_DATABASE_VERSION = 2
|
||||
|
||||
|
||||
class TPDatabase:
|
||||
|
@ -21,15 +22,22 @@ class TPDatabase:
|
|||
if '__teleport_db__' in builtins.__dict__:
|
||||
raise RuntimeError('TPDatabase object exists, you can not create more than one instance.')
|
||||
|
||||
self._table_prefix = ''
|
||||
|
||||
self.need_create = False # 数据尚未存在,需要创建
|
||||
self.need_upgrade = False # 数据库已存在但版本较低,需要升级
|
||||
self._conn_pool = None
|
||||
|
||||
@property
|
||||
def table_prefix(self):
|
||||
return self._table_prefix
|
||||
|
||||
def init_mysql(self):
|
||||
# NOT SUPPORTED YET
|
||||
pass
|
||||
|
||||
def init_sqlite(self, db_file):
|
||||
self._table_prefix = 'ts_'
|
||||
self._conn_pool = TPSqlitePool(db_file)
|
||||
|
||||
if not os.path.exists(db_file):
|
||||
|
@ -38,18 +46,29 @@ class TPDatabase:
|
|||
return
|
||||
|
||||
# 看看数据库中是否存在用户表(如果不存在,可能是一个空数据库文件),则可能是一个新安装的系统
|
||||
ret = self._conn_pool.query('SELECT COUNT(*) FROM sqlite_master where type="table" and name="ts_account";')
|
||||
ret = self.query('SELECT COUNT(*) FROM sqlite_master where type="table" and name="ts_account";')
|
||||
if ret[0][0] == 0:
|
||||
log.w('database need create.\n')
|
||||
self.need_create = True
|
||||
return
|
||||
|
||||
# 尝试从配置表中读取当前数据库版本号(如果不存在,说明是比较旧的版本了,则置为0)
|
||||
ret = self._conn_pool.query('SELECT value FROM ts_config where name="db_ver";')
|
||||
ret = self.query('SELECT value FROM ts_config where name="db_ver";')
|
||||
if 0 == len(ret):
|
||||
log.w('database need upgrade.\n')
|
||||
self.need_upgrade = True
|
||||
|
||||
def query(self, sql):
|
||||
return self._conn_pool.query(sql)
|
||||
|
||||
def exec(self, sql):
|
||||
return self._conn_pool.exec(sql)
|
||||
|
||||
|
||||
def create_and_init(self, step_begin, step_end):
|
||||
step_begin('准备创建数据表')
|
||||
create_and_init(self, step_begin, step_end)
|
||||
|
||||
|
||||
class TPDatabasePool:
|
||||
def __init__(self):
|
||||
|
@ -59,9 +78,15 @@ class TPDatabasePool:
|
|||
def query(self, sql):
|
||||
_conn = self._get_connect()
|
||||
if _conn is None:
|
||||
return list()
|
||||
return None
|
||||
return self._do_query(_conn, sql)
|
||||
|
||||
def exec(self, sql):
|
||||
_conn = self._get_connect()
|
||||
if _conn is None:
|
||||
return False
|
||||
return self._do_exec(_conn, sql)
|
||||
|
||||
def _get_connect(self):
|
||||
with self._locker:
|
||||
thread_id = threading.get_ident()
|
||||
|
@ -77,7 +102,10 @@ class TPDatabasePool:
|
|||
return None
|
||||
|
||||
def _do_query(self, conn, sql):
|
||||
return list()
|
||||
return None
|
||||
|
||||
def _do_exec(self, conn, sql):
|
||||
return None
|
||||
|
||||
|
||||
class TPSqlitePool(TPDatabasePool):
|
||||
|
@ -99,7 +127,18 @@ class TPSqlitePool(TPDatabasePool):
|
|||
db_ret = cursor.fetchall()
|
||||
return db_ret
|
||||
except sqlite3.OperationalError:
|
||||
return list()
|
||||
return None
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
def _do_exec(self, conn, sql):
|
||||
cursor = conn.cursor()
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
conn.commit()
|
||||
return True
|
||||
except sqlite3.OperationalError:
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import os
|
||||
import random
|
||||
import io
|
||||
import hashlib
|
||||
|
||||
import json
|
||||
import urllib.parse
|
||||
|
@ -23,7 +24,7 @@ from .configs import app_cfg
|
|||
|
||||
cfg = app_cfg()
|
||||
|
||||
__all__ = ['async_post_http', 'async_enc']
|
||||
__all__ = ['async_post_http', 'async_enc', 'gen_captcha', 'sec_generate_password', 'sec_verify_password']
|
||||
|
||||
|
||||
@tornado.gen.coroutine
|
||||
|
@ -67,8 +68,8 @@ def async_enc(data):
|
|||
return {'code': 0, 'data': return_data['data']['c']}
|
||||
|
||||
|
||||
_chars = 'AaCDdEeFfHJjKkLMmNnPpQRrTtVvWwXxYy34679'
|
||||
_font_dir = os.path.join(cfg.res_path, 'fonts')
|
||||
_captcha_chars = 'AaCDdEeFfHJjKkLMmNnPpQRTtVvWwXxYy34679'
|
||||
# _font_dir = os.path.join(cfg.res_path, 'fonts')
|
||||
|
||||
|
||||
def gen_captcha():
|
||||
|
@ -82,26 +83,79 @@ def gen_captcha():
|
|||
curve(color='#af6fff', width=3, number=16),
|
||||
noise(number=80, color='#eeeeee', level=3),
|
||||
text(fonts=[
|
||||
os.path.join(_font_dir, '001.ttf')
|
||||
os.path.join(cfg.res_path, 'fonts', '001.ttf')
|
||||
],
|
||||
# font_sizes=(28, 34, 36, 32),
|
||||
font_sizes=(34, 36, 32),
|
||||
font_sizes=(34, 38, 32),
|
||||
color='#63a8f5',
|
||||
squeeze_factor=1.2,
|
||||
# squeeze_factor=1.2,
|
||||
squeeze_factor=0.9,
|
||||
drawings=[
|
||||
# warp(dx_factor=0.05, dy_factor=0.05),
|
||||
rotate(angle=15),
|
||||
warp(dx_factor=0.03, dy_factor=0.03),
|
||||
rotate(angle=20),
|
||||
offset()
|
||||
]),
|
||||
# curve(color='#af6fff', width=3, number=16),
|
||||
noise(number=60, color='#eeeeee', level=2),
|
||||
noise(number=30, color='#eeeeee', level=2),
|
||||
smooth(),
|
||||
])
|
||||
|
||||
chars_t = random.sample(_chars, 4)
|
||||
chars_t = random.sample(_captcha_chars, 4)
|
||||
image = captcha_image_t(chars_t)
|
||||
|
||||
out = io.BytesIO()
|
||||
image.save(out, "jpeg", quality=100)
|
||||
# web.header('Content-Type','image/jpeg')
|
||||
return ''.join(chars_t), out.getvalue()
|
||||
|
||||
|
||||
_hex_chars = '0123456789abcdef'
|
||||
|
||||
|
||||
def sec_generate_password(password):
|
||||
"""
|
||||
根据设置的password,计算一个加盐的散列,用于保存到数据库
|
||||
@param password: string
|
||||
@return: string
|
||||
"""
|
||||
|
||||
_hash_type = '3' # 1 = md5, 2 = sha1, 3 = sha256
|
||||
|
||||
_salt_data = list()
|
||||
for i in range(16):
|
||||
_salt_data.append(random.choice(_hex_chars))
|
||||
_salt = ''.join(_salt_data)
|
||||
|
||||
h = hashlib.sha256()
|
||||
h.update(_hash_type.encode())
|
||||
h.update(_salt.encode())
|
||||
h.update(password.encode())
|
||||
_val = h.hexdigest()
|
||||
|
||||
ret = '{}:{}:{}'.format(_hash_type, _salt, _val)
|
||||
|
||||
print(ret, len(ret))
|
||||
return ret
|
||||
|
||||
|
||||
def sec_verify_password(password, sec_password):
|
||||
_sec = sec_password.split(':')
|
||||
if len(_sec) != 3:
|
||||
return False
|
||||
|
||||
if _sec[0] == '1':
|
||||
h = hashlib.md5()
|
||||
elif _sec[0] == '2':
|
||||
h = hashlib.sha1()
|
||||
elif _sec[0] == '3':
|
||||
h = hashlib.sha256()
|
||||
else:
|
||||
return False
|
||||
|
||||
h.update(_sec[0].encode())
|
||||
h.update(_sec[1].encode())
|
||||
h.update(password.encode())
|
||||
_val = h.hexdigest()
|
||||
|
||||
return _val == _sec[2]
|
||||
|
|
|
@ -5,6 +5,7 @@ import time
|
|||
import threading
|
||||
from .base import TPBaseUserAuthHandler, TPBaseAdminAuthHandler, TPBaseAdminAuthJsonHandler
|
||||
from eom_app.app.db import get_db
|
||||
from eom_app.app.util import sec_generate_password, sec_verify_password
|
||||
|
||||
|
||||
class IndexHandler(TPBaseUserAuthHandler):
|
||||
|
@ -59,6 +60,7 @@ class RpcThreadManage:
|
|||
'steps': self._threads[task_id]['steps']
|
||||
}
|
||||
if not self._threads[task_id]['running']:
|
||||
print('remove task-id', task_id)
|
||||
del self._threads[task_id]
|
||||
return ret
|
||||
else:
|
||||
|
@ -71,28 +73,67 @@ class RpcThreadManage:
|
|||
self._threads[task_id]['stop'] = True
|
||||
|
||||
def _create_db(self, tid):
|
||||
time.sleep(2)
|
||||
self._add_step_result(tid, 0, '正在初始化 1...')
|
||||
self._add_step_result(tid, 0, '正在初始化 2...')
|
||||
self._add_step_result(tid, 0, '正在初始化 3...')
|
||||
self._add_step_result(tid, 0, '正在初始化 4...')
|
||||
# x = sec_generate_password('admin')
|
||||
# print(sec_verify_password('admin', x))
|
||||
# print(sec_verify_password('.admin', x))
|
||||
|
||||
def _step_begin(msg):
|
||||
self._step_begin(tid, msg)
|
||||
|
||||
def _step_end(sid, code, msg=None):
|
||||
self._step_end(tid, sid, code, msg)
|
||||
|
||||
time.sleep(1)
|
||||
# self._add_step_result(tid, 0, '正在初始化 1...')
|
||||
|
||||
get_db().create_and_init(_step_begin, _step_end)
|
||||
|
||||
self._step_begin(tid, '操作已完成')
|
||||
|
||||
# time.sleep(1)
|
||||
# self._add_step_result(tid, 0, '正在初始化 2...')
|
||||
# time.sleep(1)
|
||||
# self._add_step_result(tid, 0, '正在初始化 3...')
|
||||
# time.sleep(1)
|
||||
# self._add_step_result(tid, 0, '正在初始化 4...')
|
||||
|
||||
# self._threads[tid]['steps'].append({'stat': 0, 'msg': '执行已结束'})
|
||||
# if self._threads[tid]['stop']:
|
||||
# self._add_step_result(tid, -1, '操作被终止')
|
||||
self._thread_end(tid)
|
||||
|
||||
def _add_step_result(self, tid, code, msg):
|
||||
if len(self._threads[tid]['steps']) > 0:
|
||||
self._threads[tid]['steps'][-1]['stat'] = 0 # 0 表示此步骤已完成
|
||||
self._threads[tid]['steps'].append({'stat': 1, 'code': code, 'msg': msg})
|
||||
def _step_begin(self, tid, msg):
|
||||
with self._lock:
|
||||
if len(self._threads[tid]['steps']) > 0:
|
||||
self._threads[tid]['steps'][-1]['stat'] = 0 # 0 表示此步骤已完成
|
||||
self._threads[tid]['steps'].append({'stat': 1, 'code': 0, 'msg': msg})
|
||||
|
||||
return len(self._threads[tid]['steps']) - 1
|
||||
|
||||
def _step_end(self, tid, sid, code, msg=None):
|
||||
with self._lock:
|
||||
try:
|
||||
self._threads[tid]['steps'][sid]['code'] = code
|
||||
self._threads[tid]['steps'][sid]['stat'] = 0 # 0 表示此步骤已完成
|
||||
if msg is not None:
|
||||
self._threads[tid]['steps'][sid]['msg'] = msg
|
||||
except:
|
||||
pass
|
||||
|
||||
return len(self._threads[tid]['steps']) - 1
|
||||
|
||||
# def _add_step_result(self, tid, code, msg):
|
||||
# if len(self._threads[tid]['steps']) > 0:
|
||||
# self._threads[tid]['steps'][-1]['stat'] = 0 # 0 表示此步骤已完成
|
||||
# self._threads[tid]['steps'].append({'stat': 1, 'code': code, 'msg': msg})
|
||||
|
||||
def _thread_end(self, tid):
|
||||
with self._lock:
|
||||
if tid in self._threads:
|
||||
self._threads[tid]['running'] = False
|
||||
if self._threads[tid]['stop']:
|
||||
self._add_step_result(tid, -1, '操作被终止')
|
||||
sid = self._step_begin(tid, '操作被终止')
|
||||
self._step_end(tid, sid, -1)
|
||||
if len(self._threads[tid]['steps']) > 0:
|
||||
self._threads[tid]['steps'][-1]['stat'] = 0
|
||||
|
||||
|
@ -123,7 +164,7 @@ class RpcHandler(TPBaseAdminAuthJsonHandler):
|
|||
# return self.write_json(-1)
|
||||
r = thread_mgr.get_task(args['tid'])
|
||||
if r is None:
|
||||
return self.write_json(0, data={'running': False, 'msg': []})
|
||||
return self.write_json(0, data={'running': False, 'steps': []})
|
||||
else:
|
||||
# del r['stop']
|
||||
return self.write_json(0, data=r)
|
||||
|
|
|
@ -67,13 +67,23 @@
|
|||
};
|
||||
|
||||
ywl.dom.btn_create_db.click(function () {
|
||||
|
||||
ywl.dom.btn_create_db.attr('disabled', 'disabled');
|
||||
|
||||
console.log('create-db-click');
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'create_db'},
|
||||
function (ret) {
|
||||
console.log('create-db:', ret);
|
||||
if (ret.code == 0) {
|
||||
ywl.get_task_ret(ret.data.task_id);
|
||||
}
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: ret.data.task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
|
||||
## ywl.get_task_ret(ret.data.task_id);
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
|
@ -83,12 +93,25 @@
|
|||
|
||||
});
|
||||
|
||||
ywl.get_task_ret = function (task_id) {
|
||||
ywl.get_task_ret = function (cb_stack, cb_args) {
|
||||
var task_id = cb_args.task_id || 0;
|
||||
if (task_id == 0) {
|
||||
console.log('task-id', task_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'get_task_ret', 'tid': task_id},
|
||||
function (ret) {
|
||||
console.log('get_task_ret:', ret);
|
||||
if (ret.code == 0) {
|
||||
if(!ret.data.running) {
|
||||
return;
|
||||
}
|
||||
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue