diff --git a/class/core/crontab_api.py b/class/core/crontab_api.py index ba77196a2..d9556241a 100755 --- a/class/core/crontab_api.py +++ b/class/core/crontab_api.py @@ -40,8 +40,7 @@ class crontab_api: startPage = (int(p) - 1) * psize pageInfo = str(startPage) + ',' + str(psize) - _list = mw.M('crontab').where('', ()).field( - self.field).limit(pageInfo).order('id desc').select() + _list = mw.M('crontab').where('', ()).field(self.field).limit(pageInfo).order('id desc').select() data = [] for i in range(len(_list)): diff --git a/data/control.conf b/data/control.conf deleted file mode 100644 index 8580e7b68..000000000 --- a/data/control.conf +++ /dev/null @@ -1 +0,0 @@ -30 \ No newline at end of file diff --git a/data/default_new.pl b/data/default_new.pl deleted file mode 100644 index d72607a41..000000000 --- a/data/default_new.pl +++ /dev/null @@ -1 +0,0 @@ -88rr2g7e \ No newline at end of file diff --git a/data/recycle_bin.pl b/data/recycle_bin.pl deleted file mode 100755 index 4791ed555..000000000 --- a/data/recycle_bin.pl +++ /dev/null @@ -1 +0,0 @@ -True \ No newline at end of file diff --git a/data/sql/default.sql b/data/sql/default.sql index 1acdaa795..bc99e4163 100755 --- a/data/sql/default.sql +++ b/data/sql/default.sql @@ -33,8 +33,9 @@ CREATE TABLE IF NOT EXISTS `crontab` ( `sname` TEXT, `sbody` TEXT, 'stype' TEXT, - `urladdress` TEXT - `add_time` TEXT + `url_address` TEXT, + `add_time` TEXT, + `update_time` TEXT ); CREATE TABLE IF NOT EXISTS `firewall` ( @@ -60,7 +61,6 @@ CREATE TABLE IF NOT EXISTS `logs` ( `uid` INTEGER DEFAULT '1', `add_time` TEXT ); -ALTER TABLE `logs` ADD COLUMN `uid` INTEGER DEFAULT '1'; CREATE TABLE IF NOT EXISTS `sites` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, @@ -73,12 +73,10 @@ CREATE TABLE IF NOT EXISTS `sites` ( `edate` TEXT, `ssl_effective_date` TEXT, `ssl_expiration_date` TEXT, - `add_time` TEXT + `add_time` TEXT, + `update_time` TEXT ); -ALTER TABLE `sites` ADD COLUMN `ssl_effective_date` TEXT DEFAULT ''; -ALTER TABLE `sites` ADD COLUMN `ssl_expiration_date` TEXT DEFAULT ''; - CREATE TABLE IF NOT EXISTS `site_types` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT @@ -94,18 +92,16 @@ CREATE TABLE IF NOT EXISTS `domain` ( CREATE TABLE IF NOT EXISTS `users` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, - `username` TEXT, + `name` TEXT, `password` TEXT, `login_ip` TEXT, `login_time` TEXT, `phone` TEXT, - `email` TEXT + `email` TEXT, + `add_time` INTEGER, + `update_time` INTEGER ); -INSERT INTO `users` (`id`, `username`, `password`, `login_ip`, `login_time`, `phone`, `email`) VALUES -(1, 'admin', '21232f297a57a5a743894a0e4a801fc3', '192.168.0.10', '2022-02-02 00:00:00', 0, 'midoks@163.com'); - - CREATE TABLE IF NOT EXISTS `tasks` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT, @@ -145,3 +141,5 @@ CREATE TABLE IF NOT EXISTS `option` ( `type` TEXT, `value` TEXT ); + +CREATE UNIQUE INDEX name_idx ON option(name); diff --git a/new_cli.sh b/new_cli.sh index 2505806f5..4d6a96388 100755 --- a/new_cli.sh +++ b/new_cli.sh @@ -64,7 +64,6 @@ mw_start_debug(){ } mw_start_panel(){ - python3 panel_task.py >> $DIR/logs/panel_task.log 2>&1 & cd ${DIR}/web && gunicorn -b :7200 -w 1 app:app } diff --git a/panel_task.py b/panel_task.py index 67344a002..9432db180 100755 --- a/panel_task.py +++ b/panel_task.py @@ -41,26 +41,12 @@ def execShell(cmdstring, cwd=None, timeout=None, shell=True): cmd = cmdstring + ' > ' + g_log_file + ' 2>&1' return mw.execShell(cmd) -def service_cmd(method): - cmd = '/etc/init.d/mw' - if os.path.exists(cmd): - execShell(cmd + ' ' + method) - return - - cmd = mw.getPanelDir() + '/scripts/init.d/mw' - if os.path.exists(cmd): - print(cmd + ' ' + method) - data = execShell(cmd + ' ' + method) - print(data) - return - def mw_async(f): def wrapper(*args, **kwargs): thr = threading.Thread(target=f, args=args, kwargs=kwargs) thr.start() return wrapper - @mw_async def restartMw(): time.sleep(1) @@ -68,7 +54,6 @@ def restartMw(): mw.execShell(cmd) - def downloadFile(url, filename): # 下载文件 try: @@ -115,23 +100,23 @@ def writeLogs(data): def runPanelTask(): try: - bash_list = model.getTaskList(status=-1) + bash_list = thisdb.getTaskList(status=-1) for task in bash_list: - model.setTaskStatus(task['id'], 0) + thisdb.setTaskStatus(task['id'], 0) - run_list = model.getTaskList(status=0) + run_list = thisdb.getTaskList(status=0) for run_task in run_list: start = int(time.time()) - model.setTaskData(run_task['id'], start=start) - model.setTaskStatus(run_task['id'], -1) + thisdb.setTaskData(run_task['id'], start=start) + thisdb.setTaskStatus(run_task['id'], -1) if run_task['type'] == 'download': argv = run_task['cmd'].split('|mw|') downloadFile(argv[0], argv[1]) elif run_task['type'] == 'execshell': execShell(run_task['cmd']) end = int(time.time()) - model.setTaskData(run_task['id'], end=end) - model.setTaskStatus(run_task['id'], 1) + thisdb.setTaskData(run_task['id'], end=end) + thisdb.setTaskStatus(run_task['id'], 1) except Exception as e: print(str(e)) @@ -371,6 +356,5 @@ def run(): startPanelTask() if __name__ == "__main__": - with app.app_context(): - run() + run() diff --git a/panel_tools.py b/panel_tools.py index f54266e9a..ec54c05f4 100755 --- a/panel_tools.py +++ b/panel_tools.py @@ -190,7 +190,7 @@ def mwcli(mw_input=0): cont = re.sub("\"53\"", "\"52\",\"53\"", cont) cont = re.sub("\"5.3.29\"", "\"5.2.17\",\"5.3.29\"", cont) mw.writeFile(php_conf, cont) - print("|-执行PHP52显示成功!") + mw.echoInfo("执行PHP52显示成功!") elif mw_input == 101: php_conf = 'plugins/php/info.json' if os.path.exists(php_conf): @@ -198,7 +198,7 @@ def mwcli(mw_input=0): cont = re.sub("\"52\",", "", cont) cont = re.sub("\"5.2.17\",", cont) mw.writeFile(php_conf, cont) - print("|-执行PHP52隐藏成功!") + mw.echoInfo("执行PHP52隐藏成功!") elif mw_input == 200: os.system(INIT_CMD + " mirror") elif mw_input == 201: diff --git a/web/admin/__init__.py b/web/admin/__init__.py index 949734855..2c3d468c9 100644 --- a/web/admin/__init__.py +++ b/web/admin/__init__.py @@ -31,8 +31,9 @@ from flask_migrate import Migrate from flask_caching import Cache from werkzeug.local import LocalProxy -from admin import model +# from admin import model from admin import setup +import thisdb from admin.model import db as sys_db @@ -68,12 +69,13 @@ app.config['SESSION_COOKIE_NAME'] = "MW_VER_1" app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=31) # db的配置 -app.config['SQLALCHEMY_DATABASE_URI'] = mw.getSqitePrefix()+config.SQLITE_PATH+"?timeout=20" # 使用 SQLite 数据库 +# app.config['SQLALCHEMY_DATABASE_URI'] = mw.getSqitePrefix()+config.SQLITE_PATH+"?timeout=20" # 使用 SQLite 数据库 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True + # 初始化db -sys_db.init_app(app) -Migrate(app, sys_db) +# sys_db.init_app(app) +# Migrate(app, sys_db) # 检查数据库是否存在。如果没有就创建它。 @@ -84,15 +86,15 @@ if not os.path.isfile(config.SQLITE_PATH): # with app.app_context(): # sys_db.create_all() -with app.app_context(): - if setup_db_required: - sys_db.create_all() - -# 初始化用户信息 -with app.app_context(): - if setup_db_required: - setup.init_admin_user() - setup.init_option() +# with app.app_context(): +# if setup_db_required: +# sys_db.create_all() + +if setup_db_required: + # 初始化用户信息 + thisdb.initPanelData() + setup.init_admin_user() + setup.init_option() setup.init_cmd() setup.init_db_system() diff --git a/web/admin/common.py b/web/admin/common.py index c1692c081..cc1be06db 100644 --- a/web/admin/common.py +++ b/web/admin/common.py @@ -10,13 +10,14 @@ import time -from admin import model +# from admin import model from admin import session +import thisdb def isLogined(): if 'login' in session and session['login'] == True and 'username' in session: username = session['username'] - info = model.getUserByName(username) + info = thisdb.getUserByName(username) if info is None: return False diff --git a/web/admin/crontab/__init__.py b/web/admin/crontab/__init__.py index 782623ca2..3e8232e40 100644 --- a/web/admin/crontab/__init__.py +++ b/web/admin/crontab/__init__.py @@ -13,7 +13,10 @@ from flask import Blueprint, render_template from flask import request from admin.user_login_check import panel_login_required -from admin.model import Crontab + +from utils.crontab import crontab as MwCrontab +import core.mw as mw +import thisdb blueprint = Blueprint('crontab', __name__, url_prefix='/crontab', template_folder='../../templates/default') @blueprint.route('/index', endpoint='index') @@ -24,26 +27,51 @@ def index(): @blueprint.route('/list', endpoint='list', methods=['GET','POST']) @panel_login_required def list(): - page = request.args.get('p', 1) - size = 10 - count = Crontab.query.count() - # print(count) - clist = Crontab.query.paginate(page=int(page), per_page=size) - # print(clist) + page = request.args.get('p', '1').strip() + limit = request.args.get('limit', '10').strip() + return MwCrontab.instance().getCrontabList(page=int(page),size=int(limit)) + +# 插件列表 +@blueprint.route('/logs', endpoint='logs', methods=['GET','POST']) +def logs(self): + sid = request.form.get('id', '') + echo = mw.M('crontab').where("id=?", (sid,)).field('echo').find() + logFile = mw.getServerDir() + '/cron/' + echo['echo'] + '.log' + if not os.path.exists(logFile): + return mw.returnData(False, '当前日志为空!') + log = mw.getLastLine(logFile, 500) + return mw.returnData(True, log) - return [] +# 获取计划任务 +@blueprint.route('/del', endpoint='del', methods=['GET','POST']) +def crontab_del(): + task_id = request.form.get('id', '') + return MwCrontab.instance().delete(task_id) +# 获取计划任务 +@blueprint.route('/get_crond_find', endpoint='get_crond_find', methods=['GET','POST']) +def get_crond_find(): + sid = request.form.get('id', '') + data = MwCrontab.instance().getCrondFind(sid) + return data +# 添加计划任务 @blueprint.route('/add', endpoint='add', methods=['GET','POST']) @panel_login_required def add(): - page = request.args.get('p', 1) - size = 10 - count = Crontab.query.count() - # print(count) - clist = Crontab.query.paginate(page=int(page), per_page=size) - # print(clist) - - return [] + request_data = {} + request_data['name'] = request.form.get('name', '') + request_data['type'] = request.form.get('type', '') + request_data['week'] = request.form.get('week', '') + request_data['where1'] = request.form.get('where1', '') + request_data['hour'] = request.form.get('hour', '') + request_data['minute'] = request.form.get('minute', '') + request_data['save'] = request.form.get('save', '') + request_data['backup_to'] = request.form.get('backupTo', '') + request_data['stype'] = request.form.get('sType', '') + request_data['sname'] = request.form.get('sName', '') + request_data['sbody'] = request.form.get('sBody', '') + request_data['url_address'] = request.form.get('urladdress', '') + return MwCrontab.instance().add(request_data) diff --git a/web/admin/dashboard/__init__.py b/web/admin/dashboard/__init__.py index c77e84623..77a962a50 100644 --- a/web/admin/dashboard/__init__.py +++ b/web/admin/dashboard/__init__.py @@ -8,236 +8,6 @@ # Author: midoks # --------------------------------------------------------------------------------- -import io -import time -from flask import Blueprint, render_template -from flask import make_response -from flask import redirect -from flask import Response -from flask import request,g - -from admin.common import isLogined -from admin.user_login_check import panel_login_required -from admin import cache,session -from admin import model -from admin.model import db,TempLogin,Users - -import core.mw as mw - - -blueprint = Blueprint('dashboard', __name__, url_prefix='/', template_folder='../../templates') -@blueprint.route('/') -@panel_login_required -def index(): - return render_template('default/index.html') - -# 安全路径 -@blueprint.route('/',endpoint='admin_safe_path',methods=['GET']) -def admin_safe_path(path): - db_path = model.getOption('admin_path') - - if isLogined(): - return redirect('/') - - if db_path == path: - return render_template('default/login.html') - - unauthorized_status = model.getOption('unauthorized_status') - if unauthorized_status == '0': - return render_template('default/path.html') - return Response(status=int(unauthorized_status)) - -# 仅针对webhook插件 -@blueprint.route("/hook", methods=['POST', 'GET']) -def webhook(): - # 兼容获取关键数据 - access_key = request.args.get('access_key', '').strip() - if access_key == '': - access_key = request.form.get('access_key', '').strip() - - params = request.args.get('params', '').strip() - if params == '': - params = request.form.get('params', '').strip() - - input_args = { - 'access_key': access_key, - 'params': params, - } - - wh_install_path = mw.getServerDir() + '/webhook' - if not os.path.exists(wh_install_path): - return mw.returnData(False, '请先安装WebHook插件!') - - package = mw.getPanelDir() + "/plugins/webhook" - if not package in sys.path: - sys.path.append(package) - - try: - import webhook_index - return webhook_index.runShellArgs(input_args) - except Exception as e: - return str(e) - -# --------------------------------------------------------------------------------- -# 定义登录入口相关方法 -# --------------------------------------------------------------------------------- - -def getErrorNum(key, limit=None): - key = mw.md5(key) - num = cache.get(key) - if not num: - num = 0 - if not limit: - return num - if limit > num: - return True - return False - - -def setErrorNum(key, empty=False, expire=3600): - key = mw.md5(key) - num = cache.get(key) - if not num: - num = 0 - else: - if empty: - cache.delete(key) - return True - cache.set(key, num + 1, expire) - return True - -def login_temp_user(token): - if len(token) != 32: - return '错误的参数!' - - skey = mw.getClientIp() + '_temp_login' - if not getErrorNum(skey, 10): - return '连续10次验证失败,禁止1小时' - - stime = int(time.time()) - - tmp_data = model.getTempLoginByToken(token) - if not tmp_data: - setErrorNum(skey) - return '验证失败!' - - if stime > int(tmp_data['expire']): - setErrorNum(skey) - return "过期" - - user_data = model.getUserById(1) - - login_addr = mw.getClientIp() + ":" + str(request.environ.get('REMOTE_PORT')) - mw.writeLog('用户临时登录', "登录成功,帐号:{1},登录IP:{2}",(user_data['name'], login_addr)) - - TempLogin.query.filter(TempLogin.id==tmp_data['id']).update({"login_time": stime, 'state': 1, 'login_addr': login_addr}) - db.session.commit() - - session['login'] = True - session['username'] = user_data['name'] - session['tmp_login'] = True - session['tmp_login_id'] = str(tmp_data['id']) - session['tmp_login_expire'] = int(tmp_data['expire']) - session['uid'] = user_data['id'] - - return redirect('/') - -# 登录页: 当设置了安全路径,本页失效。 -@blueprint.route('/login') -def login(): - - # 临时登录功能 - token = request.args.get('tmp_token', '').strip() - if token != '': - return login_temp_user(token) - - # 注销登录 - signout = request.args.get('signout', '') - if signout == 'True': - session.clear() - session['login'] = False - session['overdue'] = 0 - - db_path = model.getOption('admin_path') - if db_path == '': - return render_template('default/login.html') - else: - unauthorized_status = model.getOption('unauthorized_status') - if unauthorized_status == '0': - return render_template('default/path.html') - return Response(status=int(unauthorized_status)) - -# 验证码 -@blueprint.route('/code') -def code(): - import utils.vilidate as vilidate - vie = vilidate.vieCode() - codeImage = vie.GetCodeImage(80, 4) - out = io.BytesIO() - codeImage[0].save(out, "png") - session['code'] = mw.md5(''.join(codeImage[1]).lower()) - - img = Response(out.getvalue(), headers={'Content-Type': 'image/png'}) - return make_response(img) - -# 检查是否登录 -@blueprint.route('/check_login',methods=['GET','POST']) -def check_login(): - if isLogined(): - return mw.returnData(True,'已登录') - return mw.returnData(False,'未登录') - -# 执行登录操作 -@blueprint.route('/do_login', endpoint='do_login', methods=['POST']) -def do_login(): - username = request.form.get('username', '').strip() - password = request.form.get('password', '').strip() - code = request.form.get('code', '').strip() - - login_cache_count = 5 - login_cache_limit = cache.get('login_cache_limit') - - if 'code' in session: - if session['code'] != mw.md5(code): - if login_cache_limit == None: - login_cache_limit = 1 - else: - login_cache_limit = int(login_cache_limit) + 1 - - if login_cache_limit >= login_cache_count: - model.setOption('admin_close', 'yes') - return mw.returnJson(False, '面板已经关闭!') - - cache.set('login_cache_limit', login_cache_limit, timeout=10000) - login_cache_limit = cache.get('login_cache_limit') - login_err_msg = mw.getInfo("验证码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit))) - mw.writeLog('用户登录', login_err_msg) - return mw.returnData(False, login_err_msg) - - info = model.getUserByName(username) - password = mw.md5(password) - - if info['name'] != username or info['password'] != password: - msg = "密码错误,帐号:{1},密码:{2},登录IP:{3}", (('****', '******', request.remote_addr)) - - if login_cache_limit == None: - login_cache_limit = 1 - else: - login_cache_limit = int(login_cache_limit) + 1 - - if login_cache_limit >= login_cache_count: - model.setOption('admin_close', 'yes') - return mw.returnData(False, '面板已经关闭!') - - cache.set('login_cache_limit', login_cache_limit, timeout=10000) - login_cache_limit = cache.get('login_cache_limit') - mw.writeLog('用户登录', mw.getInfo(msg)) - return mw.returnData(-1, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit)))) - - - session['login'] = True - session['username'] = info['name'] - session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60 - - return mw.returnJson(1, '登录成功,正在跳转...') +from .dashboard import * +from .login import * diff --git a/web/admin/dashboard/dashboard.py b/web/admin/dashboard/dashboard.py new file mode 100644 index 000000000..cf1c82f0f --- /dev/null +++ b/web/admin/dashboard/dashboard.py @@ -0,0 +1,81 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import io +import time + +from flask import Blueprint, render_template +from flask import make_response +from flask import redirect +from flask import Response +from flask import request,g + +from admin.common import isLogined +from admin.user_login_check import panel_login_required +from admin import cache,session +from admin import model +from admin.model import db,TempLogin,Users + +import core.mw as mw +import thisdb + + +blueprint = Blueprint('dashboard', __name__, url_prefix='/', template_folder='../../templates') +@blueprint.route('/') +@panel_login_required +def index(): + return render_template('default/index.html') + +# 安全路径 +@blueprint.route('/',endpoint='admin_safe_path',methods=['GET']) +def admin_safe_path(path): + db_path = thisdb.getOption('admin_path') + if isLogined(): + return redirect('/') + + print(db_path,path) + if db_path == path: + return render_template('default/login.html') + + unauthorized_status = thisdb.getOption('unauthorized_status') + if unauthorized_status == '0': + return render_template('default/path.html') + return Response(status=int(unauthorized_status)) + +# 仅针对webhook插件 +@blueprint.route("/hook", methods=['POST', 'GET']) +def webhook(): + # 兼容获取关键数据 + access_key = request.args.get('access_key', '').strip() + if access_key == '': + access_key = request.form.get('access_key', '').strip() + + params = request.args.get('params', '').strip() + if params == '': + params = request.form.get('params', '').strip() + + input_args = { + 'access_key': access_key, + 'params': params, + } + + wh_install_path = mw.getServerDir() + '/webhook' + if not os.path.exists(wh_install_path): + return mw.returnData(False, '请先安装WebHook插件!') + + package = mw.getPanelDir() + "/plugins/webhook" + if not package in sys.path: + sys.path.append(package) + + try: + import webhook_index + return webhook_index.runShellArgs(input_args) + except Exception as e: + return str(e) diff --git a/web/admin/dashboard/login.py b/web/admin/dashboard/login.py new file mode 100644 index 000000000..7f1abe8eb --- /dev/null +++ b/web/admin/dashboard/login.py @@ -0,0 +1,189 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import io +import time + +from flask import Blueprint, render_template +from flask import make_response +from flask import redirect +from flask import Response +from flask import request,g + +from admin.common import isLogined +from admin.user_login_check import panel_login_required +from admin import cache,session +from admin import model +from admin.model import db,TempLogin,Users + +import core.mw as mw +import thisdb + +from .dashboard import blueprint + + +def getErrorNum(key, limit=None): + key = mw.md5(key) + num = cache.get(key) + if not num: + num = 0 + if not limit: + return num + if limit > num: + return True + return False + + +def setErrorNum(key, empty=False, expire=3600): + key = mw.md5(key) + num = cache.get(key) + if not num: + num = 0 + else: + if empty: + cache.delete(key) + return True + cache.set(key, num + 1, expire) + return True + +def login_temp_user(token): + if len(token) != 32: + return '错误的参数!' + + skey = mw.getClientIp() + '_temp_login' + if not getErrorNum(skey, 10): + return '连续10次验证失败,禁止1小时' + + stime = int(time.time()) + + tmp_data = model.getTempLoginByToken(token) + if not tmp_data: + setErrorNum(skey) + return '验证失败!' + + if stime > int(tmp_data['expire']): + setErrorNum(skey) + return "过期" + + user_data = thisdb.getUserById(1) + + login_addr = mw.getClientIp() + ":" + str(request.environ.get('REMOTE_PORT')) + mw.writeLog('用户临时登录', "登录成功,帐号:{1},登录IP:{2}",(user_data['name'], login_addr)) + + TempLogin.query.filter(TempLogin.id==tmp_data['id']).update({"login_time": stime, 'state': 1, 'login_addr': login_addr}) + db.session.commit() + + session['login'] = True + session['username'] = user_data['name'] + session['tmp_login'] = True + session['tmp_login_id'] = str(tmp_data['id']) + session['tmp_login_expire'] = int(tmp_data['expire']) + session['uid'] = user_data['id'] + + return redirect('/') + +# 登录页: 当设置了安全路径,本页失效。 +@blueprint.route('/login') +def login(): + + # 临时登录功能 + token = request.args.get('tmp_token', '').strip() + if token != '': + return login_temp_user(token) + + # 注销登录 + signout = request.args.get('signout', '') + if signout == 'True': + session.clear() + session['login'] = False + session['overdue'] = 0 + + db_path = model.getOption('admin_path') + if db_path == '': + return render_template('default/login.html') + else: + unauthorized_status = model.getOption('unauthorized_status') + if unauthorized_status == '0': + return render_template('default/path.html') + return Response(status=int(unauthorized_status)) + +# 验证码 +@blueprint.route('/code') +def code(): + import utils.vilidate as vilidate + vie = vilidate.vieCode() + codeImage = vie.GetCodeImage(80, 4) + out = io.BytesIO() + codeImage[0].save(out, "png") + session['code'] = mw.md5(''.join(codeImage[1]).lower()) + + img = Response(out.getvalue(), headers={'Content-Type': 'image/png'}) + return make_response(img) + +# 检查是否登录 +@blueprint.route('/check_login',methods=['GET','POST']) +def check_login(): + if isLogined(): + return mw.returnData(True,'已登录') + return mw.returnData(False,'未登录') + +# 执行登录操作 +@blueprint.route('/do_login', endpoint='do_login', methods=['POST']) +def do_login(): + username = request.form.get('username', '').strip() + password = request.form.get('password', '').strip() + code = request.form.get('code', '').strip() + + login_cache_count = 5 + login_cache_limit = cache.get('login_cache_limit') + + if 'code' in session: + if session['code'] != mw.md5(code): + if login_cache_limit == None: + login_cache_limit = 1 + else: + login_cache_limit = int(login_cache_limit) + 1 + + if login_cache_limit >= login_cache_count: + model.setOption('admin_close', 'yes') + return mw.returnJson(False, '面板已经关闭!') + + cache.set('login_cache_limit', login_cache_limit, timeout=10000) + login_cache_limit = cache.get('login_cache_limit') + login_err_msg = mw.getInfo("验证码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit))) + mw.writeLog('用户登录', login_err_msg) + return mw.returnData(False, login_err_msg) + + info = thisdb.getUserByName(username) + password = mw.md5(password) + + if info['name'] != username or info['password'] != password: + msg = "密码错误,帐号:{1},密码:{2},登录IP:{3}", (('****', '******', request.remote_addr)) + + if login_cache_limit == None: + login_cache_limit = 1 + else: + login_cache_limit = int(login_cache_limit) + 1 + + if login_cache_limit >= login_cache_count: + model.setOption('admin_close', 'yes') + return mw.returnData(False, '面板已经关闭!') + + cache.set('login_cache_limit', login_cache_limit, timeout=10000) + login_cache_limit = cache.get('login_cache_limit') + mw.writeLog('用户登录', mw.getInfo(msg)) + return mw.returnData(-1, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit)))) + + + session['login'] = True + session['username'] = info['name'] + session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60 + + return mw.returnJson(1, '登录成功,正在跳转...') diff --git a/web/admin/logs/__init__.py b/web/admin/logs/__init__.py index eb988b6e4..67c75234b 100644 --- a/web/admin/logs/__init__.py +++ b/web/admin/logs/__init__.py @@ -14,11 +14,9 @@ from flask import request from admin.user_login_check import panel_login_required -from admin import model -from admin.model import db, Logs - import core.mw as mw import utils.adult_log as adult_log +import thisdb # 日志页面 blueprint = Blueprint('logs', __name__, url_prefix='/logs', template_folder='../../templates') @@ -36,33 +34,18 @@ def get_log_list(): size = request.form.get('limit', '10').strip() search = request.form.get('search', '').strip() - count = Logs.query.filter_by().count() - if search != '': - pagination = Logs.query.filter_by(Logs.type.like(search) or Logs.log.like(search)).paginate(page=int(p), per_page=int(size)) - else: - pagination = Logs.query.filter_by().order_by(Logs.id.desc()).paginate(page=int(p), per_page=int(size)) - - rows = [] - for item in pagination.items: - t = {} - t['id'] = item.id - t['type'] = item.type - t['log'] = item.log - t['uid'] = item.uid - t['add_time'] = item.add_time - rows.append(t) + info = thisdb.getLogsList(page=int(p),size=int(size), search=search) data = {} - data['data'] = rows - data['page'] = mw.getPage({'count':count,'tojs':'getLogs','p':p}) + data['data'] = info['list'] + data['page'] = mw.getPage({'count':info['count'],'tojs':'getLogs','p':p,'row':size}) return data # 日志清空 @blueprint.route('/del_panel_logs', endpoint='del_panel_logs', methods=['POST']) @panel_login_required def del_panel_logs(): - model.clearLog() - # mw.M('logs').dbPos(mw.getPanelDataDir(),'panel').where('id>?', (0,)).delete() + thisdb.clearLog() mw.writeLog('面板设置', '面板操作日志已清空!') return mw.returnData(True, '面板操作日志已清空!') diff --git a/web/admin/setting/setting.py b/web/admin/setting/setting.py index f6e663e27..3b2d81a0f 100644 --- a/web/admin/setting/setting.py +++ b/web/admin/setting/setting.py @@ -16,10 +16,12 @@ from flask import Blueprint, render_template from flask import request from admin import model + from admin.user_login_check import panel_login_required import core.mw as mw +import thisdb import utils.config as utils_config @@ -41,9 +43,9 @@ def get_panel_list(): @panel_login_required def set_webname(): webname = request.form.get('webname', '') - src_webname = model.getOption('title') + src_webname = thisdb.getOption('title') if webname != src_webname: - model.setOption('title', webname) + thisdb.setOption('title', webname) return mw.returnData(True, '面板别名保存成功!') # 设置服务器IP @@ -51,9 +53,9 @@ def set_webname(): @panel_login_required def set_ip(): host_ip = request.form.get('host_ip', '') - src_host_ip = model.getOption('server_ip') + src_host_ip = thisdb.getOption('server_ip') if host_ip != src_host_ip: - model.setOption('server_ip', host_ip) + thisdb.setOption('server_ip', host_ip) return mw.returnData(True, 'IP保存成功!') # 默认备份目录 @@ -61,9 +63,9 @@ def set_ip(): @panel_login_required def set_backup_dir(): backup_path = request.form.get('backup_path', '') - src_backup_path = model.getOption('backup_path') + src_backup_path = thisdb.getOption('backup_path') if backup_path != src_backup_path: - model.setOption('backup_path', backup_path) + thisdb.setOption('backup_path', backup_path) return mw.returnData(True, '修改默认备份目录成功!') # 默认站点目录 @@ -71,9 +73,9 @@ def set_backup_dir(): @panel_login_required def set_www_dir(): sites_path = request.form.get('sites_path', '') - src_sites_path = model.getOption('sites_path') + src_sites_path = thisdb.getOption('sites_path') if sites_path != src_sites_path: - model.setOption('sites_path', sites_path) + thisdb.setOption('sites_path', sites_path) return mw.returnData(True, '修改默认建站目录成功!') @@ -102,9 +104,9 @@ def set_admin_path(): if not re.match(r"^/[\w]+$", admin_path): return mw.returnData(False, '入口地址格式不正确,示例: /mw_rand') - src_admin_path = model.getOption('admin_path') + src_admin_path = thisdb.getOption('admin_path') if admin_path != src_admin_path: - model.setOption('admin_path', admin_path[1:]) + thisdb.setOption('admin_path', admin_path[1:]) return mw.returnData(True, '修改成功!') @@ -125,7 +127,7 @@ def set_basic_auth(): is_open = False if basic_open == 'false': - model.setOption('basic_auth', json.dumps({'open':False})) + thisdb.setOption('basic_auth', json.dumps({'open':False})) mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) return mw.returnData(True, '删除BasicAuth成功!') @@ -139,7 +141,7 @@ def set_basic_auth(): data['basic_pwd'] = mw.md5(basic_pwd + salt) data['open'] = is_open - model.setOption('basic_auth', json.dumps(data)) + thisdb.setOption('basic_auth', json.dumps(data)) mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) return mw.returnData(True, '设置成功!') @@ -158,7 +160,7 @@ def set_status_code(): return mw.returnData(False, '状态码范围错误!') info = utils_config.getUnauthStatus(code=str(status_code)) - model.setOption('unauthorized_status', str(status_code)) + thisdb.setOption('unauthorized_status', str(status_code)) mw.writeLog('面板设置', '将未授权响应状态码设置为:{0}:{1}'.format(status_code,info['text'])) return mw.returnData(True, '设置成功!') @@ -166,11 +168,11 @@ def set_status_code(): @blueprint.route('/open_debug', endpoint='open_debug', methods=['POST']) @panel_login_required def open_debug(): - debug = model.getOption('debug',default='close') + debug = thisdb.getOption('debug',default='close') if debug == 'open': - model.setOption('debug','close') + thisdb.setOption('debug','close') return mw.returnData(True, '开发模式关闭!') - model.setOption('debug','open') + thisdb.setOption('debug','open') return mw.returnData(True, '开发模式开启!') @@ -178,11 +180,11 @@ def open_debug(): @blueprint.route('/close_panel', endpoint='close_panel', methods=['POST']) @panel_login_required def close_panel(): - admin_close = model.getOption('admin_close',default='no') + admin_close = thisdb.getOption('admin_close',default='no') if admin_close == 'no': - model.setOption('admin_close','yes') + thisdb.setOption('admin_close','yes') return mw.returnData(True, '开启面板成功!') - model.setOption('admin_close','no') + thisdb.setOption('admin_close','no') return mw.returnData(True, '关闭面板成功!') # 设置IPV6状态 diff --git a/web/admin/setup/option.py b/web/admin/setup/option.py index 87f691471..da08bedd0 100644 --- a/web/admin/setup/option.py +++ b/web/admin/setup/option.py @@ -12,50 +12,47 @@ import json from flask import request -from admin import model -from admin.model import db, Users - import core.mw as mw +import thisdb def init_option(): - model.setOption('title', '后羿面板') - model.setOption('recycle_bin', 'open') - model.setOption('template', 'default') + thisdb.setOption('title', '后羿面板') + thisdb.setOption('recycle_bin', 'open') + thisdb.setOption('template', 'default') # 后台面板是否关闭 - model.setOption('admin_close', 'no') + thisdb.setOption('admin_close', 'no') # 未认证状态码 - model.setOption('unauthorized_status', '0') + thisdb.setOption('unauthorized_status', '0') # 调式模式,默认关闭 - model.setOption('debug', 'close') + thisdb.setOption('debug', 'close') # basic auth 配置 - model.setOption('basic_auth', json.dumps({'open':False})) + thisdb.setOption('basic_auth', json.dumps({'open':False})) # 开启后台任务 # model.setOption('run_bg_task', 'close') # 首页展示初始化 - model.setOption('display_index', '[]') + thisdb.setOption('display_index', '[]') # 监控默认配置 - model.setOption('monitor_status', 'open', type='monitor') - model.setOption('monitor_day', '30', type='monitor') - model.setOption('monitor_only_netio', 'open', type='monitor') + thisdb.setOption('monitor_status', 'open', type='monitor') + thisdb.setOption('monitor_day', '30', type='monitor') + thisdb.setOption('monitor_only_netio', 'open', type='monitor') # 初始化安全路径 - model.setOption('admin_path', mw.getRandomString(8)) + thisdb.setOption('admin_path', mw.getRandomString(8)) ip = mw.getLocalIp() - model.setOption('server_ip', ip) + thisdb.setOption('server_ip', ip) # 默认备份目录 - model.setOption('backup_path', mw.getFatherDir()+'/backup') + thisdb.setOption('backup_path', mw.getFatherDir()+'/backup') # 默认站点目录 - model.setOption('site_path', mw.getFatherDir()+'/wwwroot') + thisdb.setOption('site_path', mw.getFatherDir()+'/wwwroot') - return True \ No newline at end of file diff --git a/web/admin/setup/user.py b/web/admin/setup/user.py index e18008d30..7c2092ace 100644 --- a/web/admin/setup/user.py +++ b/web/admin/setup/user.py @@ -14,28 +14,10 @@ from admin import model from admin.model import db, Users import core.mw as mw +import thisdb # 初始化用户信息 def init_admin_user(): - data = Users.query.filter_by(id=1).first() - if not data: - name = mw.getRandomString(8).lower() - password = mw.getRandomString(8).lower() - file_pass_pl = mw.getPanelDataDir() + '/default.pl' - mw.writeFile(file_pass_pl, password) - insert_time = mw.formatDate() - login_ip = '127.0.0.1' - add_user = Users( - name=name, - password=mw.md5(password), - login_ip=login_ip, - login_time=insert_time, - phone='', - email='', - add_time=insert_time, - update_time=insert_time) - db.session.add(add_user) - db.session.commit() - db.session.close() + thisdb.initAdminUser() return True diff --git a/web/admin/site/__init__.py b/web/admin/site/__init__.py index d51580a0c..6036672f2 100644 --- a/web/admin/site/__init__.py +++ b/web/admin/site/__init__.py @@ -19,6 +19,7 @@ from admin.user_login_check import panel_login_required from utils.plugin import plugin as MwPlugin import utils.site as site import core.mw as mw +import thisdb blueprint = Blueprint('site', __name__, url_prefix='/site', template_folder='../../templates/default') @blueprint.route('/index', endpoint='index') @@ -34,28 +35,11 @@ def list(): type_id = request.form.get('type_id', '0').strip() search = request.form.get('search', '').strip() - count = Sites.query.count() - pagination = Sites.query.paginate(page=int(p), per_page=int(limit)) - - site_list = [] - for item in pagination.items: - t = {} - t['id'] = item.id - t['name'] = item.name - t['path'] = item.path - t['index'] = item.index - t['ps'] = item.ps - t['edate'] = item.edate - t['type_id'] = item.type_id - t['status'] = item.status - t['add_time'] = item.add_time - t['update_time'] = item.update_time - site_list.append(t) + info = thisdb.getSitesList(page=int(p),size=int(limit),type_id=int(type_id), search=search) data = {} - data['data'] = site_list - data['page'] = mw.getPage({'count':count,'tojs':'getWeb','p':p, 'row':limit}) - + data['data'] = info['list'] + data['page'] = mw.getPage({'count':info['count'],'tojs':'getWeb','p':p, 'row':limit}) return data @blueprint.route('/get_site_types', endpoint='get_site_types',methods=['POST']) diff --git a/web/admin/system/system.py b/web/admin/system/system.py index 125563e2b..d224e408d 100644 --- a/web/admin/system/system.py +++ b/web/admin/system/system.py @@ -16,9 +16,9 @@ from flask import request from admin.user_login_check import panel_login_required from utils.system import monitor -import admin.model.option as option import core.mw as mw import utils.system as sys +import thisdb @@ -112,19 +112,19 @@ def set_control(): day = request.form.get('day', '') if stype == '0': - option.setOption('monitor_status', 'close', type='monitor') + thisdb.setOption('monitor_status', 'close', type='monitor') return mw.returnData(True, "设置成功!") elif stype == '1': _day = int(day) if _day < 1: return mw.returnData(False, "设置失败!") - option.setOption('monitor_day', day, type='monitor') + thisdb.setOption('monitor_day', day, type='monitor') return mw.returnData(True, "设置成功!") elif stype == '2': - option.setOption('monitor_only_netio', 'close', type='monitor') + thisdb.setOption('monitor_only_netio', 'close', type='monitor') return mw.returnData(True, "设置成功!") elif stype == '3': - option.setOption('monitor_only_netio', 'open', type='monitor') + thisdb.setOption('monitor_only_netio', 'open', type='monitor') return mw.returnData(True, "设置成功!") elif stype == 'del': if not mw.isRestart(): @@ -132,9 +132,9 @@ def set_control(): monitor.instance().clearDbFile() return mw.returnData(True, "清空监控记录成功!") else: - monitor_status = option.getOption('monitor_status', default='open', type='monitor') - monitor_day = option.getOption('monitor_day', default='30', type='monitor') - monitor_only_netio = option.getOption('monitor_only_netio', default='open', type='monitor') + monitor_status = thisdb.getOption('monitor_status', default='open', type='monitor') + monitor_day = thisdb.getOption('monitor_day', default='30', type='monitor') + monitor_only_netio = thisdb.getOption('monitor_only_netio', default='open', type='monitor') data = {} data['day'] = monitor_day if monitor_status == 'open': diff --git a/web/admin/task/__init__.py b/web/admin/task/__init__.py index e90f33a89..0567a7531 100644 --- a/web/admin/task/__init__.py +++ b/web/admin/task/__init__.py @@ -18,6 +18,7 @@ from admin.user_login_check import panel_login_required import core.mw as mw import utils.task as MwTasks +import thisdb blueprint = Blueprint('task', __name__, url_prefix='/task', template_folder='../../templates/default') @@ -25,7 +26,7 @@ blueprint = Blueprint('task', __name__, url_prefix='/task', template_folder='../ @blueprint.route('/count', endpoint='task_count') @panel_login_required def task_count(): - return str(model.getTaskUnexecutedCount()) + return str(thisdb.getTaskUnexecutedCount()) @blueprint.route('/list', endpoint='list', methods=['POST']) diff --git a/web/admin/user_login_check.py b/web/admin/user_login_check.py index 63fbb096d..c2ba5b1dd 100644 --- a/web/admin/user_login_check.py +++ b/web/admin/user_login_check.py @@ -14,17 +14,17 @@ from flask import Response from functools import wraps -from admin import model from admin import session from admin.common import isLogined +import thisdb def panel_login_required(func): @wraps(func) def wrapper(*args, **kwargs): if not isLogined(): - unauthorized_status = model.getOption('unauthorized_status') + unauthorized_status = thisdb.getOption('unauthorized_status') if unauthorized_status == '0': return render_template('default/path.html') return Response(status=int(unauthorized_status)) diff --git a/web/core/db.py b/web/core/db.py index e5c1107a8..5962ac56a 100755 --- a/web/core/db.py +++ b/web/core/db.py @@ -120,6 +120,21 @@ class Sql(): self.__OPT_FIELD = field return self + def getDbField(self,name): + sql = "PRAGMA table_info(%s)" % name + result = self.__DB_CONN.execute(sql) + data = result.fetchall() + + fields = [] + for i in data: + fields.append(i[1]) + return fields + + def getDbFieldString(self,name): + fields = self.getDbField(name) + return ','.join(fields) + + def select(self): # 查询数据集 self.__getConn() @@ -130,25 +145,40 @@ class Sql(): # print(self.__OPT_PARAM) result = self.__DB_CONN.execute(sql, self.__OPT_PARAM) data = result.fetchall() + if len(data) == 0: + return data + # 构造字曲系列 if self.__OPT_FIELD != "*": field = self.__OPT_FIELD.split(',') tmp = [] for row in data: i = 0 - tmp1 = {} + t = {} for key in field: - tmp1[key] = row[i] + t[key] = row[i] i += 1 - tmp.append(tmp1) - del(tmp1) + tmp.append(t) + del(t) data = tmp del(tmp) else: - # 将元组转换成列表 - tmp = map(list, data) + field = self.getDbField(self.__DB_TABLE) + tmp = [] + for row in data: + i = 0 + t = {} + for key in field: + t[key] = row[i] + i += 1 + tmp.append(t) + del(t) data = tmp del(tmp) + # 将元组转换成列表 + # tmp = map(list, data) + # data = tmp + # del(tmp) self.__close() return data except Exception as ex: @@ -162,7 +192,8 @@ class Sql(): sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \ self.__OPT_WHERE + self.__OPT_GROUP + self.__OPT_ORDER + self.__OPT_LIMIT - if os.path.exists('data/debug.pl'): + debug = getPanelDir()+'/data/debug.pl' + if os.path.exists(debug): print(sql, self.__OPT_PARAM) result = self.__DB_CONN.execute(sql, self.__OPT_PARAM) data = result.fetchall() @@ -199,7 +230,7 @@ class Sql(): result = self.field(keyName).select() if len(result) == 1: return result[0][keyName] - return result + return None def setField(self, keyName, keyValue): # 更新指定字段 @@ -210,7 +241,7 @@ class Sql(): result = self.limit("1").select() if len(result) == 1: return result[0] - return result + return None def count(self): # 取行数 @@ -237,7 +268,8 @@ class Sql(): self.__DB_CONN.commit() return last_id except Exception as ex: - return "error: " + str(ex) + print(str(ex)) + return 0 # 插入数据 def insert(self, pdata): diff --git a/web/static/app/crontab.js b/web/static/app/crontab.js index 1d6302e1f..b8aea37d1 100755 --- a/web/static/app/crontab.js +++ b/web/static/app/crontab.js @@ -83,6 +83,7 @@ function getBackupName(hook_data, name){ function getCronData(page){ var load = layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']}); $.post("/crontab/list?p="+page,'', function(rdata){ + console.log(rdata); layer.close(load); var cbody = ""; if(rdata == ""){ @@ -115,7 +116,7 @@ function getCronData(page){ "+rdata.data[i].cycle+"\ "+cron_save +"\ "+cron_backupto+"\ - "+rdata.data[i].addtime+"\ + "+rdata.data[i].add_time+"\ \ 执行 | \ 编辑 | \ @@ -341,7 +342,7 @@ function planAdd(){ $("#cronConfig input[name='sName']").val(sName); layer.msg('正在添加,请稍候...!',{icon:16,time:0,shade: [0.3, '#000']}); - var data = $("#cronConfig").serialize() + '&sBody='+sBody + '&urladdress=' + urladdress; + var data = $("#cronConfig").serialize() + '&sBody='+sBody; // console.log(data); $.post('/crontab/add',data,function(rdata){ if(!rdata.status) { diff --git a/web/thisdb/__init__.py b/web/thisdb/__init__.py index a2517d0f7..85125f384 100644 --- a/web/thisdb/__init__.py +++ b/web/thisdb/__init__.py @@ -14,3 +14,4 @@ from .user import * from .sites import * from .tasks import * from .logs import * +from .crontab import * diff --git a/web/thisdb/crontab.py b/web/thisdb/crontab.py new file mode 100644 index 000000000..27dad974f --- /dev/null +++ b/web/thisdb/crontab.py @@ -0,0 +1,43 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import os + +import core.mw as mw + +__field = 'id,name,type,where1,where_hour,where_minute,echo,status,save,backup_to,stype,sname,sbody,url_address,add_time,update_time' + +def addCrontab(data): + now_time = mw.formatDate() + data['add_time'] = now_time + data['update_time'] = now_time + return mw.M('crontab').insert(data) + +def getCrond(id): + return mw.M('crontab').where('id=?', (id,)).field(__field).find() + +def deleteCronById(id): + mw.M('crontab').where("id=?", (id,)).delete() + return True + +def getCrontabList( + page:int | None = 1, + size:int | None = 10, +): + start = (int(page) - 1) * size + limit = str(start) + ',' + str(size) + + cron_list = mw.M('crontab').field(__field).limit(limit).order('id desc').select() + count = mw.M('crontab').count() + + data = {} + data['count'] = count + data['list'] = cron_list + return data \ No newline at end of file diff --git a/web/thisdb/init.py b/web/thisdb/init.py index 6fa7431ff..a007d27e1 100644 --- a/web/thisdb/init.py +++ b/web/thisdb/init.py @@ -8,6 +8,20 @@ # Author: midoks # --------------------------------------------------------------------------------- +import os + +import core.mw as mw + def initPanelData(): - pass \ No newline at end of file + _dbfile = mw.getPanelDataDir() + '/panel.db' + if os.path.exists(_dbfile): + return True + sql_file = mw.getPanelDataDir() + '/sql/default.sql' + sql = mw.M().dbPos(mw.getPanelDataDir(),'panel') + csql = mw.readFile(sql_file) + csql_list = csql.split(';') + for index in range(len(csql_list)): + print(index) + sql.execute(csql_list[index], ()) + return True \ No newline at end of file diff --git a/web/thisdb/logs.py b/web/thisdb/logs.py index 967373068..d23d59719 100644 --- a/web/thisdb/logs.py +++ b/web/thisdb/logs.py @@ -8,6 +8,7 @@ # Author: midoks # --------------------------------------------------------------------------------- +import json import core.mw as mw @@ -32,4 +33,30 @@ def addLog(type, log, 'add_time':add_time, } mw.M('logs').insert(insert_data) - return True \ No newline at end of file + return True + +def getLogsList( + page:int | None = 1, + size:int | None = 10, + search: str | None = '' +): + sql_where = '' + if search != '' : + sql_where = " type like '%" + search + "%' or log like '%" + search + "%' " + + field = 'id,type,log,uid,add_time' + dbM = dbC = mw.M('logs').field(field) + + if sql_where != '': + count = mw.M('logs').field(field).where(sql_where).count() + else: + count = mw.M('logs').field(field).count() + + start = (int(page) - 1) * (int(size)) + limit = str(start) + ',' +str(size) + logs_list = mw.M('logs').field(field).limit(limit).order('id desc').select() + + data = {} + data['list'] = logs_list + data['count'] = count + return data \ No newline at end of file diff --git a/web/thisdb/option.py b/web/thisdb/option.py index 033a13925..767078425 100644 --- a/web/thisdb/option.py +++ b/web/thisdb/option.py @@ -23,8 +23,7 @@ def getOption(name, :default -> str 默认值 (可选) ''' data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value') - - if len(data) == 0: + if data is None: return default return data @@ -40,7 +39,7 @@ def getOptionByJson(name, :default -> str 默认值 (可选) ''' data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value') - if len(data) == 0: + if data is None: return default if data is not None: return json.loads(data) @@ -54,5 +53,15 @@ def setOption(name, value, :value -> object值 (必填) :type -> str 类型 (可选|默认common) ''' - mw.M('option').field('name').where('name=? and type=?',(name, type,)).setField('value', value) + + data = mw.M('option').field('name,type,value').where('name=? and type=?',(name, type,)).find() + if data is not None: + mw.M('option').field('name').where('name=? and type=?',(name, type,)).setField('value', value) + return True + add_option = { + 'name':name, + 'type':type, + 'value':value + } + mw.M('option').insert(add_option) return True \ No newline at end of file diff --git a/web/thisdb/sites.py b/web/thisdb/sites.py index b1f5a7082..e20f30071 100644 --- a/web/thisdb/sites.py +++ b/web/thisdb/sites.py @@ -11,5 +11,38 @@ import core.mw as mw def getSitesCount(): - return mw.M('sites').count() + return mw.M('sites').count() + + +def getSitesList( + page:int | None = 1, + size:int | None = 10, + type_id:int | None = 0, + search: str | None = '' +): + sql_where = '' + if search != '' : + sql_where = " name like '%" + search + "%' or ps like '%" + search + "%' " + if type_id != '' and int(type_id) >= 0 and search != '' : + sql_where = sql_where + " and type_id=" + str(type_id) + "" + if type_id != '' and int(type_id) >= 0: + sql_where = " type_id=" + str(type_id) + + + dbM = dbC = mw.M('sites').field('id,name,path,status,ps,edate,type_id,add_time,update_time') + + if sql_where != '': + count = dbC.where(sql_where).count() + else: + count = dbC.count() + + start = (int(page) - 1) * (int(size)) + limit = str(start) + ',' +str(size) + site_list = dbM.limit(limit).order('id desc').select() + + + data = {} + data['list'] = site_list + data['count'] = count + return data diff --git a/web/thisdb/tasks.py b/web/thisdb/tasks.py index 7dcab2a21..c209794d7 100644 --- a/web/thisdb/tasks.py +++ b/web/thisdb/tasks.py @@ -10,6 +10,10 @@ import core.mw as mw +# 未执行任务总数 +def getTaskUnexecutedCount() -> int: + return mw.M('tasks').where('status!=?',(1,)).count() + def addTask( name: str | None = '常用任务', cmd: str | None = None, @@ -36,4 +40,35 @@ def addTask( 'add_time':add_time, } mw.M('tasks').insert(insert_data) + return True + + +def getTaskList( + status: int | None = 1, + page: int | None = 1, + size: int | None = 10, +): + start = (page - 1) * size + limit = str(start) + ',' + str(size) + + field = 'id,name,type,start,end,status,add_time' + data = mw.M('tasks').where('', ()).field(field).limit(limit).order('id asc').select() + return data + + + +def setTaskStatus(id, + status: int | None = 0 +): + mw.M('tasks').where('id=?',(id,)).update({'status':status}) + return True + +def setTaskData(id, + start: int | None = None, + end: int | None = None, +): + if start is not None: + mw.M('tasks').where('id=?',(id,)).update({'start':start}) + if end is not None: + mw.M('tasks').where('id=?',(id,)).update({'end':end}) return True \ No newline at end of file diff --git a/web/thisdb/temp_login.py b/web/thisdb/temp_login.py new file mode 100644 index 000000000..ab75c3923 --- /dev/null +++ b/web/thisdb/temp_login.py @@ -0,0 +1,33 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import time + +from admin.model import db, TempLogin + +import core.mw as mw + +def getTempLoginByToken(token, +) -> None: + ''' + 获取用户信息通过用户名 + ''' + field = 'id,addtime,expire,login_time,login_addr,state,add_time' + data = mw.M('temp_login').where('token=?', (token,)).field(field).order('id asc').select() + return data + +def clearTempLogin()->bool: + ''' + 清空过期数据 + ''' + + now_time = int(time.time()) + mw.M('temp_login').where('expire None: ''' 获取用户信息通过用户名 ''' users_field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time' - item = mw.M('users').field(users_field).where('name=?', (name,)).select() - if len(item) == 0: + data = mw.M('users').field(users_field).where('name=?', (name,)).find() + if data is None: return None row = {} - row['id'] = item[0]['id'] - row['name'] = item[0]['name'] - row['password'] = item[0]['password'] - row['login_ip'] = item[0]['login_ip'] - row['login_time'] = item[0]['login_time'] - row['phone'] = item[0]['phone'] - row['email'] = item[0]['email'] - row['add_time'] = item[0]['add_time'] - row['update_time'] = item[0]['update_time'] + row['id'] = data['id'] + row['name'] = data['name'] + row['password'] = data['password'] + row['login_ip'] = data['login_ip'] + row['login_time'] = data['login_time'] + row['phone'] = data['phone'] + row['email'] = data['email'] + row['add_time'] = data['add_time'] + row['update_time'] = data['update_time'] return row def getUserById(id, @@ -37,19 +61,19 @@ def getUserById(id, 获取用户信息通过用户名 ''' users_field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time' - item = mw.M('users').field(users_field).where('id=?', (1,)).select() - if len(item) == 0: + data = mw.M('users').field(users_field).where('id=?', (1,)).find() + if data is None: return None row = {} - row['id'] = item[0]['id'] - row['name'] = item[0]['name'] - row['password'] = item[0]['password'] - row['login_ip'] = item[0]['login_ip'] - row['login_time'] = item[0]['login_time'] - row['phone'] = item[0]['phone'] - row['email'] = item[0]['email'] - row['add_time'] = item[0]['add_time'] - row['update_time'] = item[0]['update_time'] + row['id'] = data['id'] + row['name'] = data['name'] + row['password'] = data['password'] + row['login_ip'] = data['login_ip'] + row['login_time'] = data['login_time'] + row['phone'] = data['phone'] + row['email'] = data['email'] + row['add_time'] = data['add_time'] + row['update_time'] = data['update_time'] return row diff --git a/web/utils/crontab.py b/web/utils/crontab.py index 57a654e17..f9b2d14d5 100644 --- a/web/utils/crontab.py +++ b/web/utils/crontab.py @@ -8,4 +8,423 @@ # Author: midoks # --------------------------------------------------------------------------------- +import os +import sys +import time +import json +import threading +import multiprocessing + +from admin import model + +import core.mw as mw +import thisdb + +class crontab(object): + # lock + _instance_lock = threading.Lock() + + @classmethod + def instance(cls, *args, **kwargs): + if not hasattr(crontab, "_instance"): + with crontab._instance_lock: + if not hasattr(crontab, "_instance"): + crontab._instance = crontab(*args, **kwargs) + return crontab._instance + + # 获取指定任务数据 + def getCrondFind(self, cron_id): + return thisdb.getCrond(cron_id) + + def add(self, data): + if len(data['name']) < 1: + return mw.returnData(False, '任务名称不能为空!') + + is_check_pass, msg = self.cronCheck(data) + if not is_check_pass: + return mw.returnData(is_check_pass, msg) + + cmd, title = self.getCrondCycle(data) + cron_path = mw.getServerDir() + '/cron' + cron_name = self.getShell(data) + + cmd += ' ' + cron_path + '/' + cron_name + ' >> ' + cron_path + '/' + cron_name + '.log 2>&1' + + if not mw.isAppleSystem(): + data = self.writeShell(cmd) + if not data['status']: + return data + self.crondReload() + + add_dbdata = {} + add_dbdata['name'] = data['name'] + add_dbdata['type'] = data['type'] + add_dbdata['where1'] = data['where1'] + add_dbdata['where_hour'] = data['hour'] + add_dbdata['where_minute'] = data['minute'] + add_dbdata['save'] = data['save'] + add_dbdata['backup_to'] = data['backup_to'] + add_dbdata['sname'] = data['sname'] + add_dbdata['sbody'] = data['sbody'] + add_dbdata['stype'] = data['stype'] + add_dbdata['echo'] = cron_name + add_dbdata['url_address'] = data['url_address'] + + tid = thisdb.addCrontab(add_dbdata) + if tid > 0: + return mw.returnData(True, '添加成功') + return mw.returnData(False, '添加失败') + + def delete(self, tid): + data = thisdb.getCrond(tid) + if not self.removeForCrond(data['echo']): + return mw.returnData(False, '无法写入文件,请检查是否开启了系统加固功能!') + + cron_path = mw.getServerDir() + '/cron' + cron_file = cron_path + '/' + data['echo'] + + if os.path.exists(cron_file): + os.remove(cron_file) + cron_file = cron_path + '/' + data['echo'] + '.log' + if os.path.exists(cron_file): + os.remove(cron_file) + + thisdb.deleteCronById(tid) + msg = mw.getInfo('删除计划任务[{1}]成功!', (data['name'],)) + mw.writeLog('计划任务', msg) + return mw.returnData(True, msg) + + def getCrontabHuman(self, data): + rdata = [] + for i in range(len(data)): + t = data[i] + if t['type'] == "day": + t['type'] = '每天' + t['cycle'] = mw.getInfo('每天, {1}点{2}分 执行', (str(t['where_hour']), str(t['where_minute']))) + elif t['type'] == "day-n": + t['type'] = mw.getInfo('每{1}天', (str(t['where1']),)) + t['cycle'] = mw.getInfo('每隔{1}天, {2}点{3}分 执行', (str(t['where1']), str(t['where_hour']), str(t['where_minute']))) + elif t['type'] == "hour": + t['type'] = '每小时' + t['cycle'] = mw.getInfo('每小时, 第{1}分钟 执行', (str(t['where_minute']),)) + elif t['type'] == "hour-n": + t['type'] = mw.getInfo('每{1}小时', (str(t['where1']),)) + t['cycle'] = mw.getInfo('每{1}小时, 第{2}分钟 执行', (str(t['where1']), str(t['where_minute']))) + elif t['type'] == "minute-n": + t['type'] = mw.getInfo('每{1}分钟', (str(t['where1']),)) + t['cycle'] = mw.getInfo('每隔{1}分钟执行', (str(t['where1']),)) + elif t['type'] == "week": + t['type'] = '每周' + if not t['where1']: + t['where1'] = '0' + t['cycle'] = mw.getInfo('每周{1}, {2}点{3}分执行', (self.toWeek(int(t['where1'])), str(t['where_hour']), str(t['where_minute']))) + elif t['type'] == "month": + t['type'] = '每月' + t['cycle'] = mw.getInfo('每月, {1}日 {2}点{3}分执行', (str(t['where1']), str(t['where_hour']), str(t['where_minute']))) + rdata.append(t) + return rdata + + # 从crond删除 + def removeForCrond(self, echo): + if mw.isAppleSystem(): + return True + + u_file = '/var/spool/cron/crontabs/root' + if not os.path.exists(u_file): + file = '/var/spool/cron/root' + if not os.path.exists(file): + return False + else: + file = u_file + + conf = mw.readFile(file) + rep = ".+" + str(echo) + ".+\n" + conf = re.sub(rep, "", conf) + if not mw.writeFile(file, conf): + return False + self.crondReload() + return True + + def getCrontabList(self, + page:int | None = 1, + size:int | None = 10 + ): + info = thisdb.getCrontabList(page=int(page),size=int(size)) + + rdata = {} + rdata['data'] = self.getCrontabHuman(info['list']) + rdata['page'] = mw.getPage({'count':info['count'],'tojs':'getCronData','p':page,'row':size}) + return rdata + + def getCrondCycle(self, params): + cron_cmd = '' + title = '' + if params['type'] == "day": + cron_cmd = self.getDay(params) + title = '每天' + elif params['type'] == "day-n": + cron_cmd = self.getDay_N(params) + title = mw.getInfo('每{1}天', (params['where1'],)) + elif params['type'] == "hour": + cron_cmd = self.getHour(params) + title = '每小时' + elif params['type'] == "hour-n": + cron_cmd = self.getHour_N(params) + title = '每小时' + elif params['type'] == "minute-n": + cron_cmd = self.minute_N(params) + elif params['type'] == "week": + params['where1'] = params['week'] + cron_cmd = self.week(params) + elif params['type'] == "month": + cron_cmd = self.month(params) + return cron_cmd, title + + # 转换大写星期 + def toWeek(self, num): + wheres = { + 0: '日', + 1: '一', + 2: '二', + 3: '三', + 4: '四', + 5: '五', + 6: '六' + } + try: + return wheres[num] + except: + return '' + + # 取任务构造Day + def getDay(self, param): + cmd = "{0} {1} * * * ".format(param['minute'], param['hour']) + return cmd + + # 取任务构造Day_n + def getDay_N(self, param): + cmd = "{0} {1} */{2} * * ".format(param['minute'], param['hour'], param['where1']) + return cmd + + # 取任务构造Hour + def getHour(self, param): + cmd = "{0} * * * * ".format(param['minute']) + return cmd + + # 取任务构造Hour-N + def getHour_N(self, param): + cmd = "{0} */{1} * * * ".format(param['minute'], param['where1']) + return cmd + + # 取任务构造Minute-N + def minute_N(self, param): + cmd = "*/{0} * * * * ".format(param['where1']) + return cmd + + # 取任务构造week + def week(self, param): + cmd = "{0} {1} * * {2}".format(param['minute'], param['hour'], param['week']) + return cmd + + # 取任务构造Month + def month(self, param): + cmd = "{0} {1} {2} * * ".format(param['minute'], param['hour'], param['where1']) + return cmd + + # 参数校验 + def cronCheck(self, params): + if params['stype'] == 'site' or params['stype'] == 'database' or params['stype'].find('database_') > -1 or params['stype'] == 'logs' or params['stype'] == 'path': + if params['save'] == '': + return False, '保留份数不能为空!' + + if params['type'] == 'day': + if params['hour'] == '': + return False, '小时不能为空!' + if params['minute'] == '': + return False, '分钟不能为空!' + + if params['type'] == 'day-n': + if params['where1'] == '': + return False, '天不能为空!' + if params['hour'] == '': + return False, '小时不能为空!' + if params['minute'] == '': + return False, '分钟不能为空!' + if params['type'] == 'hour': + if params['minute'] == '': + return False, '分钟不能为空!' + + if params['type'] == 'hour-n': + if params['where1'] == '': + return False, '小时不能为空!' + if params['minute'] == '': + return False, '分钟不能为空!' + + if params['type'] == 'minute-n': + if params['where1'] == '': + return False, '分钟不能为空!' + + if params['type'] == 'week': + if params['hour'] == '': + return False, '小时不能为空!' + if params['minute'] == '': + return False, '分钟不能为空!' + + if params['type'] == 'month': + if params['where1'] == '': + return False, '日不能为空!' + if params['hour'] == '': + return False, '小时不能为空!' + if params['minute'] == '': + return False, '分钟不能为空!' + return True, 'OK' + + + # 取执行脚本 + def getShell(self, param): + # try: + stype = param['stype'] + if stype == 'toFile': + shell = param.sFile + else: + head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n" + + start_head = ''' +SCRIPT_RUN_TIME="0s" +MW_ToSeconds() +{ + SEC=$1 + if [ $SEC -lt 60 ]; then + SCRIPT_RUN_TIME="${SEC}s" + elif [ $SEC -ge 60 ] && [ $SEC -lt 3600 ];then + SCRIPT_RUN_TIME="$(( SEC / 60 ))m$(( SEC % 60 ))s" + elif [ $SEC -ge 3600 ]; then + SCRIPT_RUN_TIME="$(( SEC / 3600 ))h$(( (SEC % 3600) / 60 ))m$(( (SEC % 3600) % 60 ))s" + fi +} +START_MW_SHELL_TIME=`date +%s` +''' + + source_bin_activate = ''' +export LANG=en_US.UTF-8 +MW_PATH=%s/bin/activate +if [ -f $MW_PATH ];then + source $MW_PATH +fi''' % (mw.getPanelDir(),) + + head = head + start_head + source_bin_activate + "\n" + log = '.log' + + #所有 + if param['sname'] == 'ALL': + log = '' + + script_dir = mw.getPanelDir() + "/scripts" + source_stype = 'database' + if stype.find('database_') > -1: + plugin_name = stype.replace('database_', '') + script_dir = mw.getPanelDir() + "/plugins/" + plugin_name + "/scripts" + + source_stype = stype + stype = 'database' + + wheres = { + 'path': head + "python3 " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']), + 'site': head + "python3 " + script_dir + "/backup.py site " + param['sname'] + " " + str(param['save']), + 'database': head + "python3 " + script_dir + "/backup.py database " + param['sname'] + " " + str(param['save']), + 'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']), + 'rememory': head + "/bin/bash " + script_dir + '/rememory.sh' + } + if param['backup_to'] != 'localhost': + cfile = mw.getPluginDir() + "/" + \ + param['backup_to'] + "/index.py" + + wheres['path'] = head + "python3 " + cfile + \ + " path " + param['sname'] + " " + str(param['save']) + wheres['site'] = head + "python3 " + cfile + \ + " site " + param['sname'] + " " + str(param['save']) + wheres['database'] = head + "python3 " + cfile + " " + \ + source_stype + " " + \ + param['sname'] + " " + str(param['save']) + try: + shell = wheres[stype] + except: + if stype == 'toUrl': + shell = head + "curl -sS --connect-timeout 10 -m 60 '" + \ + param['urladdress'] + "'" + else: + shell = head + param['sbody'].replace("\r\n", "\n") + + shell += ''' +echo "----------------------------------------------------------------------------" +endDate=`date +"%Y-%m-%d %H:%M:%S"` +END_MW_SHELL_TIME=`date +"%s"` +((SHELL_COS_TIME=($END_MW_SHELL_TIME-$START_MW_SHELL_TIME))) +MW_ToSeconds $SHELL_COS_TIME +echo "★[$endDate] Successful | Script Run [$SCRIPT_RUN_TIME] " +echo "----------------------------------------------------------------------------" +''' + cron_path = mw.getServerDir() + '/cron' + if not os.path.exists(cron_path): + mw.execShell('mkdir -p ' + cron_path) + + if not 'echo' in param: + cron_name = mw.md5(mw.md5(str(time.time()) + '_mw')) + else: + cron_name = param['echo'] + file = cron_path + '/' + cron_name + mw.writeFile(file, self.checkScript(shell)) + mw.execShell('chmod 750 ' + file) + return cron_name + + # 检查脚本 + def checkScript(self, shell): + keys = ['shutdown', 'init 0', 'mkfs', 'passwd', + 'chpasswd', '--stdin', 'mkfs.ext', 'mke2fs'] + for key in keys: + shell = shell.replace(key, '[***]') + return shell + + + + # 将Shell脚本写到文件 + def writeShell(self, config): + file = '/var/spool/cron/crontabs/root' + current_os = mw.getOs() + if current_os == 'darwin': + file = '/etc/crontab' + elif current_os.startswith("freebsd"): + file = '/var/cron/tabs/root' + + if not os.path.exists(file): + file = '/var/spool/cron/root' + + if not os.path.exists(file): + mw.writeFile(file, '') + conf = mw.readFile(file) + conf += str(config) + "\n" + if mw.writeFile(file, conf): + if not os.path.exists(file): + mw.execShell("chmod 600 '" + file +"' && chown root.root " + file) + else: + mw.execShell("chmod 600 '" + file +"' && chown root.crontab " + file) + return mw.returnData(True, 'ok') + return mw.returnData(False, '文件写入失败,请检查是否开启系统加固功能!') + + # 重载配置 + def crondReload(self): + if mw.isAppleSystem(): + if os.path.exists('/etc/crontab'): + pass + else: + if os.path.exists('/etc/init.d/crond'): + mw.execShell('/etc/init.d/crond reload') + elif os.path.exists('/etc/init.d/cron'): + mw.execShell('service cron restart') + else: + mw.execShell("systemctl reload crond") + + + + diff --git a/web/utils/plugin.py b/web/utils/plugin.py index 81eda5a51..3c0bf683e 100644 --- a/web/utils/plugin.py +++ b/web/utils/plugin.py @@ -17,7 +17,6 @@ import multiprocessing from admin import model import core.mw as mw -import admin.model.option as option import thisdb class pg_thread(threading.Thread): @@ -108,7 +107,7 @@ class plugin(object): self.__index_data = json.loads(mw.readFile(self.__index)) def getIndexList(self): - indexList = option.getOptionByJson('display_index') + indexList = thisdb.getOptionByJson('display_index') plist = [] for i in indexList: tmp = i.split('-') @@ -152,30 +151,30 @@ class plugin(object): def addIndex(self, name, version): vname = name + '-' + version - indexList = option.getOptionByJson('display_index') + indexList = thisdb.getOptionByJson('display_index',default=[]) + if vname in indexList: return mw.returnData(False, '请不要重复添加!') if len(indexList) > 12: return mw.returnData(False, '首页最多只能显示12个软件!') indexList.append(vname) - option.setOption('display_index', json.dumps(indexList)) + + thisdb.setOption('display_index', json.dumps(indexList)) return mw.returnData(True, '添加成功!') def removeIndex(self, name, version): vname = name + '-' + version - indexList = option.getOptionByJson('display_index') + indexList = thisdb.getOptionByJson('display_index') if not vname in indexList: return mw.returnData(True, '删除成功!!') indexList.remove(vname) - - print(indexList) - option.setOption('display_index', json.dumps(indexList)) + thisdb.setOption('display_index', json.dumps(indexList)) return mw.returnData(True, '删除成功!') def hookInstallOption(self, hook_name, info): hn_name = 'hook_'+hook_name - src_data = option.getOptionByJson(hn_name,type='hook',default=[]) + src_data = thisdb.getOptionByJson(hn_name,type='hook',default=[]) isNeedAdd = True for x in range(len(src_data)): if src_data[x]['title'] == info['title'] and src_data[x]['name'] == info['name']: @@ -184,17 +183,17 @@ class plugin(object): if isNeedAdd: src_data.append(info) - option.setOption(hn_name, json.dumps(src_data), type='hook') + thisdb.setOption(hn_name, json.dumps(src_data), type='hook') return True def hookUninstallOption(self, hook_name, info): hn_name = 'hook_'+hook_name - src_data = option.getOptionByJson(hn_name,type='hook',default=[]) + src_data = thisdb.getOptionByJson(hn_name,type='hook',default=[]) for idx in range(len(src_data)): if src_data[idx]['name'] == info['name']: src_data.remove(src_data[idx]) break - option.setOption(hn_name, json.dumps(src_data), type='hook') + thisdb.setOption(hn_name, json.dumps(src_data), type='hook') return True def hookInstall(self, info): @@ -316,7 +315,7 @@ class plugin(object): return '' def checkIndexList(self, name, version): - indexList = option.getOptionByJson('display_index') + indexList = thisdb.getOptionByJson('display_index',default=[]) for i in indexList: t = i.split('-') if t[0] == name: @@ -426,15 +425,28 @@ class plugin(object): return pInfo def makeCoexistData(self, data): - plugins_t = [] + plugins = [] if type(data['versions']) == list and 'coexist' in data and data['coexist']: data_t = self.makeCoexist(data) for index in range(len(data_t)): - plugins_t.append(data_t[index]) + plugins.append(data_t[index]) else: pg = self.getPluginInfo(data) - plugins_t.append(pg) - return plugins_t + plugins.append(pg) + return plugins + + def makeCoexistDataInstalled(self, data): + plugins = [] + if type(data['versions']) == list and 'coexist' in data and data['coexist']: + data_t = self.makeCoexist(data) + for index in range(len(data_t)): + if data_t[index]['setup']: + plugins.append(data_t[index]) + else: + pg = self.getPluginInfo(data) + if pg['setup']: + plugins.append(pg) + return plugins # 对多版本共存进行处理 def makeCoexistList(self, data, @@ -449,12 +461,11 @@ class plugin(object): if plugin_type == None or plugin_type == '0': return self.makeCoexistData(data) # 已经安装 - if plugin_type == '-1': - return self.makeCoexistData(data) + if str(plugin_type) == '-1': + return self.makeCoexistDataInstalled(data) return plugins_t - def getPluginList(self, name, keyword: str | None = None, type: str | None = None,