diff --git a/plugins/data_query/nosql_memcached.py b/plugins/data_query/nosql_memcached.py index 1f4b55b9e..4b392aad8 100755 --- a/plugins/data_query/nosql_memcached.py +++ b/plugins/data_query/nosql_memcached.py @@ -11,8 +11,12 @@ import re import json import pymemcache -sys.path.append(os.getcwd() + "/class/core") -import mw +try: + sys.path.append(os.getcwd() + "/class/core") + import mw +except Exception as e: + import core.mw as mw + def singleton(cls): _instance = {} diff --git a/plugins/data_query/nosql_mongodb.py b/plugins/data_query/nosql_mongodb.py index d65fef434..286c63e45 100755 --- a/plugins/data_query/nosql_mongodb.py +++ b/plugins/data_query/nosql_mongodb.py @@ -12,8 +12,11 @@ import yaml from bson.objectid import ObjectId from bson.json_util import dumps -sys.path.append(os.getcwd() + "/class/core") -import mw +try: + sys.path.append(os.getcwd() + "/class/core") + import mw +except Exception as e: + import core.mw as mw def singleton(cls): _instance = {} diff --git a/plugins/data_query/nosql_redis.py b/plugins/data_query/nosql_redis.py index 439175d41..65eb675e5 100755 --- a/plugins/data_query/nosql_redis.py +++ b/plugins/data_query/nosql_redis.py @@ -7,8 +7,13 @@ import time import re import redis -sys.path.append(os.getcwd() + "/class/core") -import mw + +try: + sys.path.append(os.getcwd() + "/class/core") + import mw +except Exception as e: + import core.mw as mw + # def getPluginName(): # return 'data_query' diff --git a/plugins/data_query/sql_mysql.py b/plugins/data_query/sql_mysql.py index 3de3920aa..ee8c83fbf 100755 --- a/plugins/data_query/sql_mysql.py +++ b/plugins/data_query/sql_mysql.py @@ -8,9 +8,11 @@ import re import pymongo import json - -sys.path.append(os.getcwd() + "/class/core") -import mw +try: + sys.path.append(os.getcwd() + "/class/core") + import mw +except Exception as e: + import core.mw as mw def singleton(cls): _instance = {} diff --git a/web/admin/__init__.py b/web/admin/__init__.py index a819cc369..b1c51c334 100644 --- a/web/admin/__init__.py +++ b/web/admin/__init__.py @@ -118,7 +118,7 @@ def inject_global_variables(): data = utils_config.getGlobalVar() g_config = { 'version': ver, - 'title' : '面板', + 'title' : 'MW面板', 'ip' : '127.0.0.1' } return dict(config=g_config, data=data) diff --git a/web/admin/plugins/__init__.py b/web/admin/plugins/__init__.py index 4a857c5db..8e8a1a1e2 100644 --- a/web/admin/plugins/__init__.py +++ b/web/admin/plugins/__init__.py @@ -17,8 +17,10 @@ from flask import request from utils.mwplugin import MwPlugin from admin.user_login_check import panel_login_required -import core.mw as mw +from admin import model +import core.mw as mw +import utils.config as utils_config blueprint = Blueprint('plugins', __name__, url_prefix='/plugins', template_folder='../../templates/default') @@ -121,6 +123,25 @@ def uninstall(): pg = MwPlugin.instance() return pg.uninstall(name, version) +# 文件读取 +@blueprint.route('/menu', endpoint='menu', methods=['GET']) +@panel_login_required +def menu(): + data = utils_config.getGlobalVar() + pg = MwPlugin.instance() + tag = request.args.get('tag', '') + + hook_menu = model.getOptionByJson('hook_menu',type='hook',default=[]) + content = '' + for menu_data in hook_menu: + if tag == menu_data['name'] and 'path' in menu_data: + t = pg.menuGetAbsPath(tag, menu_data['path']) + content = mw.readFile(t) + #------------------------------------------------------------ + data['hook_tag'] = tag + data['plugin_content'] = content + return render_template('plugin_menu.html', data=data) + # 文件读取 @blueprint.route('/file', endpoint='file', methods=['GET']) @panel_login_required diff --git a/web/admin/setting/__init__.py b/web/admin/setting/__init__.py index 43f58e8d4..30f24ec68 100644 --- a/web/admin/setting/__init__.py +++ b/web/admin/setting/__init__.py @@ -47,6 +47,25 @@ def set_ip(): model.setOption('server_ip', host_ip) return mw.returnData(True, 'IP保存成功!') +# 默认备份目录 +@blueprint.route('/set_backup_dir', endpoint='set_backup_dir', methods=['POST']) +def set_backup_dir(): + backup_path = request.form.get('backup_path', '') + src_backup_path = model.getOption('backup_path') + if backup_path != src_backup_path: + model.setOption('backup_path', backup_path) + return mw.returnData(True, '修改默认备份目录成功!') + +# 默认站点目录 +@blueprint.route('/set_www_dir', endpoint='set_www_dir', methods=['POST']) +def set_www_dir(): + sites_path = request.form.get('sites_path', '') + src_sites_path = model.getOption('sites_path') + if sites_path != src_sites_path: + model.setOption('sites_path', sites_path) + return mw.returnData(True, '修改默认建站目录成功!') + + # 设置安全入口 @blueprint.route('/set_admin_path', endpoint='set_admin_path', methods=['POST']) def set_admin_path(): diff --git a/web/admin/setup/option.py b/web/admin/setup/option.py index 959e7e29e..c941b71d5 100644 --- a/web/admin/setup/option.py +++ b/web/admin/setup/option.py @@ -35,4 +35,10 @@ def init_option(): model.setOption('admin_path', mw.getRandomString(8)) model.setOption('server_ip', '127.0.0.1') + # 默认备份目录 + model.setOption('backup_path', mw.getFatherDir()+'/backup') + # 默认站点目录 + model.setOption('site_path', mw.getFatherDir()+'/wwwroot') + + return True \ No newline at end of file diff --git a/web/core/mw.py b/web/core/mw.py index edef5be41..ebd52bd5f 100644 --- a/web/core/mw.py +++ b/web/core/mw.py @@ -511,6 +511,12 @@ def isNumber(s): return False +def debugLog(*data): + if isDebugMode(): + print(data) + return True + + def writeLog(stype, msg, args=()): # 写日志 uid = 0 @@ -540,6 +546,106 @@ def M(table): sql = db.Sql() return sql.table(table) +# ------------------------------ openresty start ----------------------------- + +def restartWeb(): + return opWeb("reload") + +def isInstalledWeb(): + path = getServerDir() + '/openresty/nginx/sbin/nginx' + if os.path.exists(path): + return True + return False + +def opWeb(method): + if not isInstalledWeb(): + return False + + # systemd + systemd = '/lib/systemd/system/openresty.service' + if os.path.exists(systemd): + execShell('systemctl ' + method + ' openresty') + return True + + # initd + initd = getServerDir() + '/openresty/init.d/openresty' + + if os.path.exists(initd): + execShell(initd + ' ' + method) + return True + + return False +def opLuaMake(cmd_name): + path = getServerDir() + '/web_conf/nginx/lua/lua.conf' + root_dir = getServerDir() + '/web_conf/nginx/lua/' + cmd_name + dst_path = getServerDir() + '/web_conf/nginx/lua/' + cmd_name + '.lua' + def_path = getServerDir() + '/web_conf/nginx/lua/empty.lua' + + if not os.path.exists(root_dir): + execShell('mkdir -p ' + root_dir) + + files = [] + for fl in os.listdir(root_dir): + suffix = getFileSuffix(fl) + if suffix != 'lua': + continue + flpath = os.path.join(root_dir, fl) + files.append(flpath) + + if len(files) > 0: + def_path = dst_path + content = '' + for f in files: + t = readFile(f) + f_base = os.path.basename(f) + content += '-- ' + '*' * 20 + ' ' + f_base + ' start ' + '*' * 20 + "\n" + content += t + content += "\n" + '-- ' + '*' * 20 + ' ' + f_base + ' end ' + '*' * 20 + "\n" + writeFile(dst_path, content) + else: + if os.path.exists(dst_path): + os.remove(dst_path) + + conf = readFile(path) + conf = re.sub(cmd_name + ' (.*);', + cmd_name + " " + def_path + ";", conf) + writeFile(path, conf) + + +def opLuaInitFile(): + opLuaMake('init_by_lua_file') + + +def opLuaInitWorkerFile(): + opLuaMake('init_worker_by_lua_file') + + +def opLuaInitAccessFile(): + opLuaMake('access_by_lua_file') + + +def opLuaMakeAll(): + opLuaInitFile() + opLuaInitWorkerFile() + opLuaInitAccessFile() + +# ------------------------------ openresty end ----------------------------- + +# --------------------------------------------------------------------------------- +# 数据库 START +# --------------------------------------------------------------------------------- +def getMyORM(): + ''' + 获取MySQL资源的ORM + ''' + import core.orm as orm + o = orm.ORM() + return o +# --------------------------------------------------------------------------------- +# 数据库 START +# --------------------------------------------------------------------------------- + + # --------------------------------------------------------------------------------- # 打印相关 START # --------------------------------------------------------------------------------- diff --git a/web/core/orm.py b/web/core/orm.py new file mode 100755 index 000000000..89ba623e9 --- /dev/null +++ b/web/core/orm.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +import re +import os +import sys + +import pymysql.cursors + + +class ORM: + __DB_PASS = None + __DB_USER = 'root' + __DB_PORT = 3306 + __DB_NAME = '' + __DB_HOST = 'localhost' + __DB_CONN = None + __DB_CUR = None + __DB_ERR = None + __DB_CNF = '/etc/my.cnf' + __DB_TIMEOUT=1 + __DB_SOCKET = '/www/server/mysql/mysql.sock' + + __DB_CHARSET = "utf8" + + def __Conn(self): + # print(self.__DB_HOST, self.__DB_USER, self.__DB_PASS, self.__DB_SOCKET) + '''连接数据库''' + try: + + if self.__DB_HOST != 'localhost': + try: + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + cursorclass=pymysql.cursors.DictCursor) + except Exception as e: + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + cursorclass=pymysql.cursors.DictCursor) + elif os.path.exists(self.__DB_SOCKET): + try: + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + unix_socket=self.__DB_SOCKET, cursorclass=pymysql.cursors.DictCursor) + except Exception as e: + self.__DB_HOST = '127.0.0.1' + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + unix_socket=self.__DB_SOCKET, cursorclass=pymysql.cursors.DictCursor) + else: + try: + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + cursorclass=pymysql.cursors.DictCursor) + except Exception as e: + self.__DB_HOST = '127.0.0.1' + self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS, + database=self.__DB_NAME, + port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT, + cursorclass=pymysql.cursors.DictCursor) + + self.__DB_CUR = self.__DB_CONN.cursor() + return True + except Exception as e: + self.__DB_ERR = e + return False + + def setDbConf(self, conf): + self.__DB_CNF = conf + + def setSocket(self, sock): + self.__DB_SOCKET = sock + + def setCharset(self, charset): + self.__DB_CHARSET = charset + + def setHost(self, host): + self.__DB_HOST = host + + def setPort(self, port): + self.__DB_PORT = port + + def setUser(self, user): + self.__DB_USER = user + + def setPwd(self, pwd): + self.__DB_PASS = pwd + + def getPwd(self): + return self.__DB_PASS + + def setTimeout(self, timeout = 1): + self.__DB_TIMEOUT = timeout + return True + + def setDbName(self, name): + self.__DB_NAME = name + + def execute(self, sql): + # 执行SQL语句返回受影响行 + if not self.__Conn(): + return self.__DB_ERR + try: + result = self.__DB_CUR.execute(sql) + self.__DB_CONN.commit() + self.__Close() + return result + except Exception as ex: + return ex + + def ping(self): + try: + self.__DB_CONN.ping() + except Exception as e: + print(e) + return True + + def query(self, sql): + # 执行SQL语句返回数据集 + if not self.__Conn(): + return self.__DB_ERR + try: + self.__DB_CUR.execute(sql) + result = self.__DB_CUR.fetchall() + # print(result) + # 将元组转换成列表 + # data = map(list, result) + self.__Close() + return result + except Exception as ex: + return ex + + def __Close(self): + # 关闭连接 + self.__DB_CUR.close() + self.__DB_CONN.close() diff --git a/web/utils/config.py b/web/utils/config.py index 06dbd3766..766da0e21 100644 --- a/web/utils/config.py +++ b/web/utils/config.py @@ -29,5 +29,9 @@ def getGlobalVar(): # 服务器时间 sformat = 'date +"%Y-%m-%d %H:%M:%S %Z %z"' data['systemdate'] = mw.execShell(sformat)[0].strip() + + + data['hook_menu'] = model.getOptionByJson('hook_menu',type='hook',default=[]) + data['hook_global_static'] = model.getOptionByJson('hook_global_static',type='hook',default=[]) return data \ No newline at end of file diff --git a/web/utils/mwplugin.py b/web/utils/mwplugin.py index 226b302be..4904672ac 100644 --- a/web/utils/mwplugin.py +++ b/web/utils/mwplugin.py @@ -144,6 +144,12 @@ class MwPlugin(object): plist = self.checkStatusMThreads(plist) return plist + def menuGetAbsPath(self, tag, path): + if path[0:1] == '/': + return path + else: + return mw.getPluginDir() + '/' + tag + '/' + path + def addIndex(self, name, version): vname = name + '-' + version indexList = option.getOptionByJson('display_index') @@ -167,6 +173,66 @@ class MwPlugin(object): option.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=[]) + isNeedAdd = True + for x in range(len(src_data)): + if src_data[x]['title'] == info['title'] and src_data[x]['name'] == info['name']: + isNeedAdd = False + + if isNeedAdd: + src_data.append(info) + + option.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=[]) + 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') + return True + + def hookInstall(self, info): + valid_hook = ['backup', 'database'] + valid_list_hook = ['menu', 'global_static', 'site_cb'] + if 'hook' in info: + hooks = info['hook'] + for h in hooks: + hooks_type = type(h) + if hooks_type == dict: + tag = h['tag'] + if tag in valid_list_hook: + self.hookInstallOption(tag, h[tag]) + elif hooks_type == str: + for x in hooks: + if x in valid_hook: + self.hookInstallOption(x, info) + return True + return False + + def hookUninstall(self, info): + valid_hook = ['backup', 'database'] + valid_list_hook = ['menu', 'global_static', 'site_cb'] + if 'hook' in info: + hooks = info['hook'] + for h in hooks: + hooks_type = type(h) + if hooks_type == dict: + tag = h['tag'] + if tag in valid_list_hook: + self.hookUninstallOption(tag, h[tag]) + elif hooks_type == str: + for x in hooks: + if x in valid_hook: + self.hookUninstallOption(x, info) + return True + return False + def install(self, name, version, upgrade: bool | None = None ): @@ -193,11 +259,12 @@ class MwPlugin(object): version ) + self.hookInstall(info_data) title = '{0}[{1}-{2}]'.format(msg_head,name,version) model.addTask(name=title,cmd=exec_bash, status=0) - if mw.isDebugMode(): - print(exec_bash) + # 调式日志 + mw.debugLog(exec_bash) return mw.returnData(True, '已将安装任务添加到队列!') # 卸载插件 @@ -220,13 +287,10 @@ class MwPlugin(object): info_data['shell'], version ) - + self.hookUninstall(info_data) data = mw.execShell(exec_bash) - if mw.isDebugMode(): - print(exec_bash) - print(data[0], data[1]) - self.removeIndex(name, version) + mw.debugLog(exec_bash, data) return mw.returnData(True, '卸载执行成功!') # 插件搜索匹配