pull/632/head
Mr Chen 6 months ago
parent 1826adf50e
commit d4cfd90ccd
  1. 3
      class/core/crontab_api.py
  2. 1
      data/control.conf
  3. 1
      data/default_new.pl
  4. 1
      data/recycle_bin.pl
  5. 24
      data/sql/default.sql
  6. 1
      new_cli.sh
  7. 30
      panel_task.py
  8. 4
      panel_tools.py
  9. 22
      web/admin/__init__.py
  10. 5
      web/admin/common.py
  11. 60
      web/admin/crontab/__init__.py
  12. 234
      web/admin/dashboard/__init__.py
  13. 81
      web/admin/dashboard/dashboard.py
  14. 189
      web/admin/dashboard/login.py
  15. 27
      web/admin/logs/__init__.py
  16. 40
      web/admin/setting/setting.py
  17. 35
      web/admin/setup/option.py
  18. 22
      web/admin/setup/user.py
  19. 24
      web/admin/site/__init__.py
  20. 16
      web/admin/system/system.py
  21. 3
      web/admin/task/__init__.py
  22. 4
      web/admin/user_login_check.py
  23. 52
      web/core/db.py
  24. 5
      web/static/app/crontab.js
  25. 1
      web/thisdb/__init__.py
  26. 43
      web/thisdb/crontab.py
  27. 16
      web/thisdb/init.py
  28. 27
      web/thisdb/logs.py
  29. 15
      web/thisdb/option.py
  30. 33
      web/thisdb/sites.py
  31. 35
      web/thisdb/tasks.py
  32. 33
      web/thisdb/temp_login.py
  33. 68
      web/thisdb/user.py
  34. 419
      web/utils/crontab.py
  35. 51
      web/utils/plugin.py

@ -40,8 +40,7 @@ class crontab_api:
startPage = (int(p) - 1) * psize startPage = (int(p) - 1) * psize
pageInfo = str(startPage) + ',' + str(psize) pageInfo = str(startPage) + ',' + str(psize)
_list = mw.M('crontab').where('', ()).field( _list = mw.M('crontab').where('', ()).field(self.field).limit(pageInfo).order('id desc').select()
self.field).limit(pageInfo).order('id desc').select()
data = [] data = []
for i in range(len(_list)): for i in range(len(_list)):

@ -33,8 +33,9 @@ CREATE TABLE IF NOT EXISTS `crontab` (
`sname` TEXT, `sname` TEXT,
`sbody` TEXT, `sbody` TEXT,
'stype' TEXT, 'stype' TEXT,
`urladdress` TEXT `url_address` TEXT,
`add_time` TEXT `add_time` TEXT,
`update_time` TEXT
); );
CREATE TABLE IF NOT EXISTS `firewall` ( CREATE TABLE IF NOT EXISTS `firewall` (
@ -60,7 +61,6 @@ CREATE TABLE IF NOT EXISTS `logs` (
`uid` INTEGER DEFAULT '1', `uid` INTEGER DEFAULT '1',
`add_time` TEXT `add_time` TEXT
); );
ALTER TABLE `logs` ADD COLUMN `uid` INTEGER DEFAULT '1';
CREATE TABLE IF NOT EXISTS `sites` ( CREATE TABLE IF NOT EXISTS `sites` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, `id` INTEGER PRIMARY KEY AUTOINCREMENT,
@ -73,12 +73,10 @@ CREATE TABLE IF NOT EXISTS `sites` (
`edate` TEXT, `edate` TEXT,
`ssl_effective_date` TEXT, `ssl_effective_date` TEXT,
`ssl_expiration_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` ( CREATE TABLE IF NOT EXISTS `site_types` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, `id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT `name` TEXT
@ -94,18 +92,16 @@ CREATE TABLE IF NOT EXISTS `domain` (
CREATE TABLE IF NOT EXISTS `users` ( CREATE TABLE IF NOT EXISTS `users` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, `id` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` TEXT, `name` TEXT,
`password` TEXT, `password` TEXT,
`login_ip` TEXT, `login_ip` TEXT,
`login_time` TEXT, `login_time` TEXT,
`phone` 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` ( CREATE TABLE IF NOT EXISTS `tasks` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, `id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT, `name` TEXT,
@ -145,3 +141,5 @@ CREATE TABLE IF NOT EXISTS `option` (
`type` TEXT, `type` TEXT,
`value` TEXT `value` TEXT
); );
CREATE UNIQUE INDEX name_idx ON option(name);

@ -64,7 +64,6 @@ mw_start_debug(){
} }
mw_start_panel(){ mw_start_panel(){
python3 panel_task.py >> $DIR/logs/panel_task.log 2>&1 &
cd ${DIR}/web && gunicorn -b :7200 -w 1 app:app cd ${DIR}/web && gunicorn -b :7200 -w 1 app:app
} }

@ -41,26 +41,12 @@ def execShell(cmdstring, cwd=None, timeout=None, shell=True):
cmd = cmdstring + ' > ' + g_log_file + ' 2>&1' cmd = cmdstring + ' > ' + g_log_file + ' 2>&1'
return mw.execShell(cmd) 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 mw_async(f):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
thr = threading.Thread(target=f, args=args, kwargs=kwargs) thr = threading.Thread(target=f, args=args, kwargs=kwargs)
thr.start() thr.start()
return wrapper return wrapper
@mw_async @mw_async
def restartMw(): def restartMw():
time.sleep(1) time.sleep(1)
@ -68,7 +54,6 @@ def restartMw():
mw.execShell(cmd) mw.execShell(cmd)
def downloadFile(url, filename): def downloadFile(url, filename):
# 下载文件 # 下载文件
try: try:
@ -115,23 +100,23 @@ def writeLogs(data):
def runPanelTask(): def runPanelTask():
try: try:
bash_list = model.getTaskList(status=-1) bash_list = thisdb.getTaskList(status=-1)
for task in bash_list: 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: for run_task in run_list:
start = int(time.time()) start = int(time.time())
model.setTaskData(run_task['id'], start=start) thisdb.setTaskData(run_task['id'], start=start)
model.setTaskStatus(run_task['id'], -1) thisdb.setTaskStatus(run_task['id'], -1)
if run_task['type'] == 'download': if run_task['type'] == 'download':
argv = run_task['cmd'].split('|mw|') argv = run_task['cmd'].split('|mw|')
downloadFile(argv[0], argv[1]) downloadFile(argv[0], argv[1])
elif run_task['type'] == 'execshell': elif run_task['type'] == 'execshell':
execShell(run_task['cmd']) execShell(run_task['cmd'])
end = int(time.time()) end = int(time.time())
model.setTaskData(run_task['id'], end=end) thisdb.setTaskData(run_task['id'], end=end)
model.setTaskStatus(run_task['id'], 1) thisdb.setTaskStatus(run_task['id'], 1)
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
@ -371,6 +356,5 @@ def run():
startPanelTask() startPanelTask()
if __name__ == "__main__": if __name__ == "__main__":
with app.app_context():
run() run()

@ -190,7 +190,7 @@ def mwcli(mw_input=0):
cont = re.sub("\"53\"", "\"52\",\"53\"", cont) cont = re.sub("\"53\"", "\"52\",\"53\"", cont)
cont = re.sub("\"5.3.29\"", "\"5.2.17\",\"5.3.29\"", cont) cont = re.sub("\"5.3.29\"", "\"5.2.17\",\"5.3.29\"", cont)
mw.writeFile(php_conf, cont) mw.writeFile(php_conf, cont)
print("|-执行PHP52显示成功!") mw.echoInfo("执行PHP52显示成功!")
elif mw_input == 101: elif mw_input == 101:
php_conf = 'plugins/php/info.json' php_conf = 'plugins/php/info.json'
if os.path.exists(php_conf): if os.path.exists(php_conf):
@ -198,7 +198,7 @@ def mwcli(mw_input=0):
cont = re.sub("\"52\",", "", cont) cont = re.sub("\"52\",", "", cont)
cont = re.sub("\"5.2.17\",", cont) cont = re.sub("\"5.2.17\",", cont)
mw.writeFile(php_conf, cont) mw.writeFile(php_conf, cont)
print("|-执行PHP52隐藏成功!") mw.echoInfo("执行PHP52隐藏成功!")
elif mw_input == 200: elif mw_input == 200:
os.system(INIT_CMD + " mirror") os.system(INIT_CMD + " mirror")
elif mw_input == 201: elif mw_input == 201:

@ -31,8 +31,9 @@ from flask_migrate import Migrate
from flask_caching import Cache from flask_caching import Cache
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from admin import model # from admin import model
from admin import setup from admin import setup
import thisdb
from admin.model import db as sys_db 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) app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=31)
# db的配置 # 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 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 初始化db # 初始化db
sys_db.init_app(app) # sys_db.init_app(app)
Migrate(app, sys_db) # Migrate(app, sys_db)
# 检查数据库是否存在。如果没有就创建它。 # 检查数据库是否存在。如果没有就创建它。
@ -84,13 +86,13 @@ if not os.path.isfile(config.SQLITE_PATH):
# with app.app_context(): # with app.app_context():
# sys_db.create_all() # sys_db.create_all()
with app.app_context(): # with app.app_context():
if setup_db_required: # if setup_db_required:
sys_db.create_all() # sys_db.create_all()
# 初始化用户信息 if setup_db_required:
with app.app_context(): # 初始化用户信息
if setup_db_required: thisdb.initPanelData()
setup.init_admin_user() setup.init_admin_user()
setup.init_option() setup.init_option()
setup.init_cmd() setup.init_cmd()

@ -10,13 +10,14 @@
import time import time
from admin import model # from admin import model
from admin import session from admin import session
import thisdb
def isLogined(): def isLogined():
if 'login' in session and session['login'] == True and 'username' in session: if 'login' in session and session['login'] == True and 'username' in session:
username = session['username'] username = session['username']
info = model.getUserByName(username) info = thisdb.getUserByName(username)
if info is None: if info is None:
return False return False

@ -13,7 +13,10 @@ from flask import Blueprint, render_template
from flask import request from flask import request
from admin.user_login_check import panel_login_required 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 = Blueprint('crontab', __name__, url_prefix='/crontab', template_folder='../../templates/default')
@blueprint.route('/index', endpoint='index') @blueprint.route('/index', endpoint='index')
@ -24,26 +27,51 @@ def index():
@blueprint.route('/list', endpoint='list', methods=['GET','POST']) @blueprint.route('/list', endpoint='list', methods=['GET','POST'])
@panel_login_required @panel_login_required
def list(): def list():
page = request.args.get('p', 1) page = request.args.get('p', '1').strip()
size = 10 limit = request.args.get('limit', '10').strip()
count = Crontab.query.count() return MwCrontab.instance().getCrontabList(page=int(page),size=int(limit))
# print(count)
clist = Crontab.query.paginate(page=int(page), per_page=size) # 插件列表
# print(clist) @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']) @blueprint.route('/add', endpoint='add', methods=['GET','POST'])
@panel_login_required @panel_login_required
def add(): def add():
page = request.args.get('p', 1) request_data = {}
size = 10 request_data['name'] = request.form.get('name', '')
count = Crontab.query.count() request_data['type'] = request.form.get('type', '')
# print(count) request_data['week'] = request.form.get('week', '')
clist = Crontab.query.paginate(page=int(page), per_page=size) request_data['where1'] = request.form.get('where1', '')
# print(clist) request_data['hour'] = request.form.get('hour', '')
request_data['minute'] = request.form.get('minute', '')
return [] 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)

@ -8,236 +8,6 @@
# Author: midoks <midoks@163.com> # Author: midoks <midoks@163.com>
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
import io
import time
from flask import Blueprint, render_template from .dashboard import *
from flask import make_response from .login import *
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('/<path>',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 = "<a style='color: red'>密码错误</a>,帐号:{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, '登录成功,正在跳转...')

@ -0,0 +1,81 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
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('/<path>',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)

@ -0,0 +1,189 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
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 = "<a style='color: red'>密码错误</a>,帐号:{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, '登录成功,正在跳转...')

@ -14,11 +14,9 @@ from flask import request
from admin.user_login_check import panel_login_required 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 core.mw as mw
import utils.adult_log as adult_log import utils.adult_log as adult_log
import thisdb
# 日志页面 # 日志页面
blueprint = Blueprint('logs', __name__, url_prefix='/logs', template_folder='../../templates') 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() size = request.form.get('limit', '10').strip()
search = request.form.get('search', '').strip() search = request.form.get('search', '').strip()
count = Logs.query.filter_by().count() info = thisdb.getLogsList(page=int(p),size=int(size), search=search)
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)
data = {} data = {}
data['data'] = rows data['data'] = info['list']
data['page'] = mw.getPage({'count':count,'tojs':'getLogs','p':p}) data['page'] = mw.getPage({'count':info['count'],'tojs':'getLogs','p':p,'row':size})
return data return data
# 日志清空 # 日志清空
@blueprint.route('/del_panel_logs', endpoint='del_panel_logs', methods=['POST']) @blueprint.route('/del_panel_logs', endpoint='del_panel_logs', methods=['POST'])
@panel_login_required @panel_login_required
def del_panel_logs(): def del_panel_logs():
model.clearLog() thisdb.clearLog()
# mw.M('logs').dbPos(mw.getPanelDataDir(),'panel').where('id>?', (0,)).delete()
mw.writeLog('面板设置', '面板操作日志已清空!') mw.writeLog('面板设置', '面板操作日志已清空!')
return mw.returnData(True, '面板操作日志已清空!') return mw.returnData(True, '面板操作日志已清空!')

@ -16,10 +16,12 @@ from flask import Blueprint, render_template
from flask import request from flask import request
from admin import model from admin import model
from admin.user_login_check import panel_login_required from admin.user_login_check import panel_login_required
import core.mw as mw import core.mw as mw
import thisdb
import utils.config as utils_config import utils.config as utils_config
@ -41,9 +43,9 @@ def get_panel_list():
@panel_login_required @panel_login_required
def set_webname(): def set_webname():
webname = request.form.get('webname', '') webname = request.form.get('webname', '')
src_webname = model.getOption('title') src_webname = thisdb.getOption('title')
if webname != src_webname: if webname != src_webname:
model.setOption('title', webname) thisdb.setOption('title', webname)
return mw.returnData(True, '面板别名保存成功!') return mw.returnData(True, '面板别名保存成功!')
# 设置服务器IP # 设置服务器IP
@ -51,9 +53,9 @@ def set_webname():
@panel_login_required @panel_login_required
def set_ip(): def set_ip():
host_ip = request.form.get('host_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: if host_ip != src_host_ip:
model.setOption('server_ip', host_ip) thisdb.setOption('server_ip', host_ip)
return mw.returnData(True, 'IP保存成功!') return mw.returnData(True, 'IP保存成功!')
# 默认备份目录 # 默认备份目录
@ -61,9 +63,9 @@ def set_ip():
@panel_login_required @panel_login_required
def set_backup_dir(): def set_backup_dir():
backup_path = request.form.get('backup_path', '') 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: if backup_path != src_backup_path:
model.setOption('backup_path', backup_path) thisdb.setOption('backup_path', backup_path)
return mw.returnData(True, '修改默认备份目录成功!') return mw.returnData(True, '修改默认备份目录成功!')
# 默认站点目录 # 默认站点目录
@ -71,9 +73,9 @@ def set_backup_dir():
@panel_login_required @panel_login_required
def set_www_dir(): def set_www_dir():
sites_path = request.form.get('sites_path', '') 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: if sites_path != src_sites_path:
model.setOption('sites_path', sites_path) thisdb.setOption('sites_path', sites_path)
return mw.returnData(True, '修改默认建站目录成功!') return mw.returnData(True, '修改默认建站目录成功!')
@ -102,9 +104,9 @@ def set_admin_path():
if not re.match(r"^/[\w]+$", admin_path): if not re.match(r"^/[\w]+$", admin_path):
return mw.returnData(False, '入口地址格式不正确,示例: /mw_rand') 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: if admin_path != src_admin_path:
model.setOption('admin_path', admin_path[1:]) thisdb.setOption('admin_path', admin_path[1:])
return mw.returnData(True, '修改成功!') return mw.returnData(True, '修改成功!')
@ -125,7 +127,7 @@ def set_basic_auth():
is_open = False is_open = False
if basic_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) mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open)
return mw.returnData(True, '删除BasicAuth成功!') return mw.returnData(True, '删除BasicAuth成功!')
@ -139,7 +141,7 @@ def set_basic_auth():
data['basic_pwd'] = mw.md5(basic_pwd + salt) data['basic_pwd'] = mw.md5(basic_pwd + salt)
data['open'] = is_open data['open'] = is_open
model.setOption('basic_auth', json.dumps(data)) thisdb.setOption('basic_auth', json.dumps(data))
mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open)
return mw.returnData(True, '设置成功!') return mw.returnData(True, '设置成功!')
@ -158,7 +160,7 @@ def set_status_code():
return mw.returnData(False, '状态码范围错误!') return mw.returnData(False, '状态码范围错误!')
info = utils_config.getUnauthStatus(code=str(status_code)) 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'])) mw.writeLog('面板设置', '将未授权响应状态码设置为:{0}:{1}'.format(status_code,info['text']))
return mw.returnData(True, '设置成功!') return mw.returnData(True, '设置成功!')
@ -166,11 +168,11 @@ def set_status_code():
@blueprint.route('/open_debug', endpoint='open_debug', methods=['POST']) @blueprint.route('/open_debug', endpoint='open_debug', methods=['POST'])
@panel_login_required @panel_login_required
def open_debug(): def open_debug():
debug = model.getOption('debug',default='close') debug = thisdb.getOption('debug',default='close')
if debug == 'open': if debug == 'open':
model.setOption('debug','close') thisdb.setOption('debug','close')
return mw.returnData(True, '开发模式关闭!') return mw.returnData(True, '开发模式关闭!')
model.setOption('debug','open') thisdb.setOption('debug','open')
return mw.returnData(True, '开发模式开启!') return mw.returnData(True, '开发模式开启!')
@ -178,11 +180,11 @@ def open_debug():
@blueprint.route('/close_panel', endpoint='close_panel', methods=['POST']) @blueprint.route('/close_panel', endpoint='close_panel', methods=['POST'])
@panel_login_required @panel_login_required
def close_panel(): def close_panel():
admin_close = model.getOption('admin_close',default='no') admin_close = thisdb.getOption('admin_close',default='no')
if admin_close == 'no': if admin_close == 'no':
model.setOption('admin_close','yes') thisdb.setOption('admin_close','yes')
return mw.returnData(True, '开启面板成功!') return mw.returnData(True, '开启面板成功!')
model.setOption('admin_close','no') thisdb.setOption('admin_close','no')
return mw.returnData(True, '关闭面板成功!') return mw.returnData(True, '关闭面板成功!')
# 设置IPV6状态 # 设置IPV6状态

@ -12,50 +12,47 @@ import json
from flask import request from flask import request
from admin import model
from admin.model import db, Users
import core.mw as mw import core.mw as mw
import thisdb
def init_option(): def init_option():
model.setOption('title', '后羿面板') thisdb.setOption('title', '后羿面板')
model.setOption('recycle_bin', 'open') thisdb.setOption('recycle_bin', 'open')
model.setOption('template', 'default') 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 配置 # 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('run_bg_task', 'close')
# 首页展示初始化 # 首页展示初始化
model.setOption('display_index', '[]') thisdb.setOption('display_index', '[]')
# 监控默认配置 # 监控默认配置
model.setOption('monitor_status', 'open', type='monitor') thisdb.setOption('monitor_status', 'open', type='monitor')
model.setOption('monitor_day', '30', type='monitor') thisdb.setOption('monitor_day', '30', type='monitor')
model.setOption('monitor_only_netio', 'open', 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() 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 return True

@ -14,28 +14,10 @@ from admin import model
from admin.model import db, Users from admin.model import db, Users
import core.mw as mw import core.mw as mw
import thisdb
# 初始化用户信息 # 初始化用户信息
def init_admin_user(): def init_admin_user():
data = Users.query.filter_by(id=1).first() thisdb.initAdminUser()
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()
return True return True

@ -19,6 +19,7 @@ from admin.user_login_check import panel_login_required
from utils.plugin import plugin as MwPlugin from utils.plugin import plugin as MwPlugin
import utils.site as site import utils.site as site
import core.mw as mw import core.mw as mw
import thisdb
blueprint = Blueprint('site', __name__, url_prefix='/site', template_folder='../../templates/default') blueprint = Blueprint('site', __name__, url_prefix='/site', template_folder='../../templates/default')
@blueprint.route('/index', endpoint='index') @blueprint.route('/index', endpoint='index')
@ -34,28 +35,11 @@ def list():
type_id = request.form.get('type_id', '0').strip() type_id = request.form.get('type_id', '0').strip()
search = request.form.get('search', '').strip() search = request.form.get('search', '').strip()
count = Sites.query.count() info = thisdb.getSitesList(page=int(p),size=int(limit),type_id=int(type_id), search=search)
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)
data = {} data = {}
data['data'] = site_list data['data'] = info['list']
data['page'] = mw.getPage({'count':count,'tojs':'getWeb','p':p, 'row':limit}) data['page'] = mw.getPage({'count':info['count'],'tojs':'getWeb','p':p, 'row':limit})
return data return data
@blueprint.route('/get_site_types', endpoint='get_site_types',methods=['POST']) @blueprint.route('/get_site_types', endpoint='get_site_types',methods=['POST'])

@ -16,9 +16,9 @@ from flask import request
from admin.user_login_check import panel_login_required from admin.user_login_check import panel_login_required
from utils.system import monitor from utils.system import monitor
import admin.model.option as option
import core.mw as mw import core.mw as mw
import utils.system as sys import utils.system as sys
import thisdb
@ -112,19 +112,19 @@ def set_control():
day = request.form.get('day', '') day = request.form.get('day', '')
if stype == '0': if stype == '0':
option.setOption('monitor_status', 'close', type='monitor') thisdb.setOption('monitor_status', 'close', type='monitor')
return mw.returnData(True, "设置成功!") return mw.returnData(True, "设置成功!")
elif stype == '1': elif stype == '1':
_day = int(day) _day = int(day)
if _day < 1: if _day < 1:
return mw.returnData(False, "设置失败!") return mw.returnData(False, "设置失败!")
option.setOption('monitor_day', day, type='monitor') thisdb.setOption('monitor_day', day, type='monitor')
return mw.returnData(True, "设置成功!") return mw.returnData(True, "设置成功!")
elif stype == '2': elif stype == '2':
option.setOption('monitor_only_netio', 'close', type='monitor') thisdb.setOption('monitor_only_netio', 'close', type='monitor')
return mw.returnData(True, "设置成功!") return mw.returnData(True, "设置成功!")
elif stype == '3': elif stype == '3':
option.setOption('monitor_only_netio', 'open', type='monitor') thisdb.setOption('monitor_only_netio', 'open', type='monitor')
return mw.returnData(True, "设置成功!") return mw.returnData(True, "设置成功!")
elif stype == 'del': elif stype == 'del':
if not mw.isRestart(): if not mw.isRestart():
@ -132,9 +132,9 @@ def set_control():
monitor.instance().clearDbFile() monitor.instance().clearDbFile()
return mw.returnData(True, "清空监控记录成功!") return mw.returnData(True, "清空监控记录成功!")
else: else:
monitor_status = option.getOption('monitor_status', default='open', type='monitor') monitor_status = thisdb.getOption('monitor_status', default='open', type='monitor')
monitor_day = option.getOption('monitor_day', default='30', type='monitor') monitor_day = thisdb.getOption('monitor_day', default='30', type='monitor')
monitor_only_netio = option.getOption('monitor_only_netio', default='open', type='monitor') monitor_only_netio = thisdb.getOption('monitor_only_netio', default='open', type='monitor')
data = {} data = {}
data['day'] = monitor_day data['day'] = monitor_day
if monitor_status == 'open': if monitor_status == 'open':

@ -18,6 +18,7 @@ from admin.user_login_check import panel_login_required
import core.mw as mw import core.mw as mw
import utils.task as MwTasks import utils.task as MwTasks
import thisdb
blueprint = Blueprint('task', __name__, url_prefix='/task', template_folder='../../templates/default') 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') @blueprint.route('/count', endpoint='task_count')
@panel_login_required @panel_login_required
def task_count(): def task_count():
return str(model.getTaskUnexecutedCount()) return str(thisdb.getTaskUnexecutedCount())
@blueprint.route('/list', endpoint='list', methods=['POST']) @blueprint.route('/list', endpoint='list', methods=['POST'])

@ -14,17 +14,17 @@ from flask import Response
from functools import wraps from functools import wraps
from admin import model
from admin import session from admin import session
from admin.common import isLogined from admin.common import isLogined
import thisdb
def panel_login_required(func): def panel_login_required(func):
@wraps(func) @wraps(func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
if not isLogined(): if not isLogined():
unauthorized_status = model.getOption('unauthorized_status') unauthorized_status = thisdb.getOption('unauthorized_status')
if unauthorized_status == '0': if unauthorized_status == '0':
return render_template('default/path.html') return render_template('default/path.html')
return Response(status=int(unauthorized_status)) return Response(status=int(unauthorized_status))

@ -120,6 +120,21 @@ class Sql():
self.__OPT_FIELD = field self.__OPT_FIELD = field
return self 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): def select(self):
# 查询数据集 # 查询数据集
self.__getConn() self.__getConn()
@ -130,25 +145,40 @@ class Sql():
# print(self.__OPT_PARAM) # print(self.__OPT_PARAM)
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM) result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
data = result.fetchall() data = result.fetchall()
if len(data) == 0:
return data
# 构造字曲系列 # 构造字曲系列
if self.__OPT_FIELD != "*": if self.__OPT_FIELD != "*":
field = self.__OPT_FIELD.split(',') field = self.__OPT_FIELD.split(',')
tmp = [] tmp = []
for row in data: for row in data:
i = 0 i = 0
tmp1 = {} t = {}
for key in field: for key in field:
tmp1[key] = row[i] t[key] = row[i]
i += 1 i += 1
tmp.append(tmp1) tmp.append(t)
del(tmp1) del(t)
data = tmp data = tmp
del(tmp) del(tmp)
else: else:
# 将元组转换成列表 field = self.getDbField(self.__DB_TABLE)
tmp = map(list, data) 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 data = tmp
del(tmp) del(tmp)
# 将元组转换成列表
# tmp = map(list, data)
# data = tmp
# del(tmp)
self.__close() self.__close()
return data return data
except Exception as ex: except Exception as ex:
@ -162,7 +192,8 @@ class Sql():
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \ sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \
self.__OPT_WHERE + self.__OPT_GROUP + self.__OPT_ORDER + self.__OPT_LIMIT 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) print(sql, self.__OPT_PARAM)
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM) result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
data = result.fetchall() data = result.fetchall()
@ -199,7 +230,7 @@ class Sql():
result = self.field(keyName).select() result = self.field(keyName).select()
if len(result) == 1: if len(result) == 1:
return result[0][keyName] return result[0][keyName]
return result return None
def setField(self, keyName, keyValue): def setField(self, keyName, keyValue):
# 更新指定字段 # 更新指定字段
@ -210,7 +241,7 @@ class Sql():
result = self.limit("1").select() result = self.limit("1").select()
if len(result) == 1: if len(result) == 1:
return result[0] return result[0]
return result return None
def count(self): def count(self):
# 取行数 # 取行数
@ -237,7 +268,8 @@ class Sql():
self.__DB_CONN.commit() self.__DB_CONN.commit()
return last_id return last_id
except Exception as ex: except Exception as ex:
return "error: " + str(ex) print(str(ex))
return 0
# 插入数据 # 插入数据
def insert(self, pdata): def insert(self, pdata):

@ -83,6 +83,7 @@ function getBackupName(hook_data, name){
function getCronData(page){ function getCronData(page){
var load = layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']}); var load = layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']});
$.post("/crontab/list?p="+page,'', function(rdata){ $.post("/crontab/list?p="+page,'', function(rdata){
console.log(rdata);
layer.close(load); layer.close(load);
var cbody = ""; var cbody = "";
if(rdata == ""){ if(rdata == ""){
@ -115,7 +116,7 @@ function getCronData(page){
<td>"+rdata.data[i].cycle+"</td>\ <td>"+rdata.data[i].cycle+"</td>\
<td>"+cron_save +"</td>\ <td>"+cron_save +"</td>\
<td>"+cron_backupto+"</td>\ <td>"+cron_backupto+"</td>\
<td>"+rdata.data[i].addtime+"</td>\ <td>"+rdata.data[i].add_time+"</td>\
<td>\ <td>\
<a href=\"javascript:startTask("+rdata.data[i].id+");\" class='btlink'>执行</a> | \ <a href=\"javascript:startTask("+rdata.data[i].id+");\" class='btlink'>执行</a> | \
<a href=\"javascript:editTaskInfo('"+rdata.data[i].id+"');\" class='btlink'>编辑</a> | \ <a href=\"javascript:editTaskInfo('"+rdata.data[i].id+"');\" class='btlink'>编辑</a> | \
@ -341,7 +342,7 @@ function planAdd(){
$("#cronConfig input[name='sName']").val(sName); $("#cronConfig input[name='sName']").val(sName);
layer.msg('正在添加,请稍候...!',{icon:16,time:0,shade: [0.3, '#000']}); 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); // console.log(data);
$.post('/crontab/add',data,function(rdata){ $.post('/crontab/add',data,function(rdata){
if(!rdata.status) { if(!rdata.status) {

@ -14,3 +14,4 @@ from .user import *
from .sites import * from .sites import *
from .tasks import * from .tasks import *
from .logs import * from .logs import *
from .crontab import *

@ -0,0 +1,43 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
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

@ -8,6 +8,20 @@
# Author: midoks <midoks@163.com> # Author: midoks <midoks@163.com>
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
import os
import core.mw as mw
def initPanelData(): def initPanelData():
pass _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

@ -8,6 +8,7 @@
# Author: midoks <midoks@163.com> # Author: midoks <midoks@163.com>
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
import json
import core.mw as mw import core.mw as mw
@ -33,3 +34,29 @@ def addLog(type, log,
} }
mw.M('logs').insert(insert_data) mw.M('logs').insert(insert_data)
return True 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

@ -23,8 +23,7 @@ def getOption(name,
:default -> str 默认值 (可选) :default -> str 默认值 (可选)
''' '''
data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value') data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value')
if data is None:
if len(data) == 0:
return default return default
return data return data
@ -40,7 +39,7 @@ def getOptionByJson(name,
:default -> str 默认值 (可选) :default -> str 默认值 (可选)
''' '''
data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value') 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 default
if data is not None: if data is not None:
return json.loads(data) return json.loads(data)
@ -54,5 +53,15 @@ def setOption(name, value,
:value -> object值 (必填) :value -> object值 (必填)
:type -> str 类型 (可选|默认common) :type -> str 类型 (可选|默认common)
''' '''
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) mw.M('option').field('name').where('name=? and type=?',(name, type,)).setField('value', value)
return True return True
add_option = {
'name':name,
'type':type,
'value':value
}
mw.M('option').insert(add_option)
return True

@ -13,3 +13,36 @@ import core.mw as mw
def getSitesCount(): 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

@ -10,6 +10,10 @@
import core.mw as mw import core.mw as mw
# 未执行任务总数
def getTaskUnexecutedCount() -> int:
return mw.M('tasks').where('status!=?',(1,)).count()
def addTask( def addTask(
name: str | None = '常用任务', name: str | None = '常用任务',
cmd: str | None = None, cmd: str | None = None,
@ -37,3 +41,34 @@ def addTask(
} }
mw.M('tasks').insert(insert_data) mw.M('tasks').insert(insert_data)
return True 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

@ -0,0 +1,33 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
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<?', (now_time)).delete()
return True

@ -10,25 +10,49 @@
import core.mw as mw import core.mw as mw
# 初始化用户信息
def initAdminUser():
data = mw.M('users').field('id').where('id=?', (1,)).find()
if data is None:
name = mw.getRandomString(8).lower()
password = mw.getRandomString(8).lower()
insert_time = mw.formatDate()
login_ip = '127.0.0.1'
add_user = {
'name':name,
'password':mw.md5(password),
'login_ip':login_ip,
'login_time':insert_time,
'phone':'',
'email':'',
'add_time':insert_time,
'update_time':insert_time
}
file_pass_pl = mw.getPanelDataDir() + '/default.pl'
mw.writeFile(file_pass_pl, password)
mw.M('users').insert(add_user)
return True
def getUserByName(name, def getUserByName(name,
) -> None: ) -> None:
''' '''
获取用户信息通过用户名 获取用户信息通过用户名
''' '''
users_field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time' 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() data = mw.M('users').field(users_field).where('name=?', (name,)).find()
if len(item) == 0: if data is None:
return None return None
row = {} row = {}
row['id'] = item[0]['id'] row['id'] = data['id']
row['name'] = item[0]['name'] row['name'] = data['name']
row['password'] = item[0]['password'] row['password'] = data['password']
row['login_ip'] = item[0]['login_ip'] row['login_ip'] = data['login_ip']
row['login_time'] = item[0]['login_time'] row['login_time'] = data['login_time']
row['phone'] = item[0]['phone'] row['phone'] = data['phone']
row['email'] = item[0]['email'] row['email'] = data['email']
row['add_time'] = item[0]['add_time'] row['add_time'] = data['add_time']
row['update_time'] = item[0]['update_time'] row['update_time'] = data['update_time']
return row return row
def getUserById(id, 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' 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() data = mw.M('users').field(users_field).where('id=?', (1,)).find()
if len(item) == 0: if data is None:
return None return None
row = {} row = {}
row['id'] = item[0]['id'] row['id'] = data['id']
row['name'] = item[0]['name'] row['name'] = data['name']
row['password'] = item[0]['password'] row['password'] = data['password']
row['login_ip'] = item[0]['login_ip'] row['login_ip'] = data['login_ip']
row['login_time'] = item[0]['login_time'] row['login_time'] = data['login_time']
row['phone'] = item[0]['phone'] row['phone'] = data['phone']
row['email'] = item[0]['email'] row['email'] = data['email']
row['add_time'] = item[0]['add_time'] row['add_time'] = data['add_time']
row['update_time'] = item[0]['update_time'] row['update_time'] = data['update_time']
return row return row

@ -8,4 +8,423 @@
# Author: midoks <midoks@163.com> # Author: midoks <midoks@163.com>
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
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")

@ -17,7 +17,6 @@ import multiprocessing
from admin import model from admin import model
import core.mw as mw import core.mw as mw
import admin.model.option as option
import thisdb import thisdb
class pg_thread(threading.Thread): class pg_thread(threading.Thread):
@ -108,7 +107,7 @@ class plugin(object):
self.__index_data = json.loads(mw.readFile(self.__index)) self.__index_data = json.loads(mw.readFile(self.__index))
def getIndexList(self): def getIndexList(self):
indexList = option.getOptionByJson('display_index') indexList = thisdb.getOptionByJson('display_index')
plist = [] plist = []
for i in indexList: for i in indexList:
tmp = i.split('-') tmp = i.split('-')
@ -152,30 +151,30 @@ class plugin(object):
def addIndex(self, name, version): def addIndex(self, name, version):
vname = name + '-' + version vname = name + '-' + version
indexList = option.getOptionByJson('display_index') indexList = thisdb.getOptionByJson('display_index',default=[])
if vname in indexList: if vname in indexList:
return mw.returnData(False, '请不要重复添加!') return mw.returnData(False, '请不要重复添加!')
if len(indexList) > 12: if len(indexList) > 12:
return mw.returnData(False, '首页最多只能显示12个软件!') return mw.returnData(False, '首页最多只能显示12个软件!')
indexList.append(vname) indexList.append(vname)
option.setOption('display_index', json.dumps(indexList))
thisdb.setOption('display_index', json.dumps(indexList))
return mw.returnData(True, '添加成功!') return mw.returnData(True, '添加成功!')
def removeIndex(self, name, version): def removeIndex(self, name, version):
vname = name + '-' + version vname = name + '-' + version
indexList = option.getOptionByJson('display_index') indexList = thisdb.getOptionByJson('display_index')
if not vname in indexList: if not vname in indexList:
return mw.returnData(True, '删除成功!!') return mw.returnData(True, '删除成功!!')
indexList.remove(vname) indexList.remove(vname)
thisdb.setOption('display_index', json.dumps(indexList))
print(indexList)
option.setOption('display_index', json.dumps(indexList))
return mw.returnData(True, '删除成功!') return mw.returnData(True, '删除成功!')
def hookInstallOption(self, hook_name, info): def hookInstallOption(self, hook_name, info):
hn_name = 'hook_'+hook_name 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 isNeedAdd = True
for x in range(len(src_data)): for x in range(len(src_data)):
if src_data[x]['title'] == info['title'] and src_data[x]['name'] == info['name']: if src_data[x]['title'] == info['title'] and src_data[x]['name'] == info['name']:
@ -184,17 +183,17 @@ class plugin(object):
if isNeedAdd: if isNeedAdd:
src_data.append(info) 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 return True
def hookUninstallOption(self, hook_name, info): def hookUninstallOption(self, hook_name, info):
hn_name = 'hook_'+hook_name 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)): for idx in range(len(src_data)):
if src_data[idx]['name'] == info['name']: if src_data[idx]['name'] == info['name']:
src_data.remove(src_data[idx]) src_data.remove(src_data[idx])
break break
option.setOption(hn_name, json.dumps(src_data), type='hook') thisdb.setOption(hn_name, json.dumps(src_data), type='hook')
return True return True
def hookInstall(self, info): def hookInstall(self, info):
@ -316,7 +315,7 @@ class plugin(object):
return '' return ''
def checkIndexList(self, name, version): def checkIndexList(self, name, version):
indexList = option.getOptionByJson('display_index') indexList = thisdb.getOptionByJson('display_index',default=[])
for i in indexList: for i in indexList:
t = i.split('-') t = i.split('-')
if t[0] == name: if t[0] == name:
@ -426,15 +425,28 @@ class plugin(object):
return pInfo return pInfo
def makeCoexistData(self, data): def makeCoexistData(self, data):
plugins_t = [] plugins = []
if type(data['versions']) == list and 'coexist' in data and data['coexist']: if type(data['versions']) == list and 'coexist' in data and data['coexist']:
data_t = self.makeCoexist(data) data_t = self.makeCoexist(data)
for index in range(len(data_t)): for index in range(len(data_t)):
plugins_t.append(data_t[index]) plugins.append(data_t[index])
else: else:
pg = self.getPluginInfo(data) pg = self.getPluginInfo(data)
plugins_t.append(pg) plugins.append(pg)
return plugins_t 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, def makeCoexistList(self, data,
@ -449,12 +461,11 @@ class plugin(object):
if plugin_type == None or plugin_type == '0': if plugin_type == None or plugin_type == '0':
return self.makeCoexistData(data) return self.makeCoexistData(data)
# 已经安装 # 已经安装
if plugin_type == '-1': if str(plugin_type) == '-1':
return self.makeCoexistData(data) return self.makeCoexistDataInstalled(data)
return plugins_t return plugins_t
def getPluginList(self, name, def getPluginList(self, name,
keyword: str | None = None, keyword: str | None = None,
type: str | None = None, type: str | None = None,

Loading…
Cancel
Save