mdserver-web/route/__init__.py

412 lines
12 KiB
Python
Raw Normal View History

2018-10-25 04:40:45 -04:00
# coding:utf-8
2018-12-24 21:52:39 -05:00
import sys
import io
import os
import time
import shutil
2018-12-25 10:48:29 -05:00
import uuid
2018-12-24 21:52:39 -05:00
2021-04-30 23:45:29 -04:00
# reload(sys)
# sys.setdefaultencoding('utf-8')
2019-01-09 11:52:03 -05:00
2019-02-18 03:21:31 -05:00
2018-12-25 02:12:59 -05:00
from datetime import timedelta
2018-12-24 21:52:39 -05:00
from flask import Flask
from flask import render_template
2018-12-25 04:43:28 -05:00
from flask import make_response
from flask import Response
from flask import session
from flask import request
2018-12-25 10:48:29 -05:00
from flask import redirect
from flask import url_for
2022-03-23 03:30:28 -04:00
from flask import render_template_string, abort
2019-12-08 08:10:22 -05:00
from flask_caching import Cache
2018-12-25 10:48:29 -05:00
from flask_session import Session
2018-12-24 21:52:39 -05:00
sys.path.append(os.getcwd() + "/class/core")
2021-05-09 10:48:04 -04:00
# sys.path.append("/usr/local/lib/python3.6/site-packages")
2019-12-08 08:10:22 -05:00
2018-12-25 10:48:29 -05:00
import db
2020-07-10 03:57:25 -04:00
import mw
2019-01-18 04:11:29 -05:00
import config_api
2018-12-24 21:52:39 -05:00
app = Flask(__name__, template_folder='templates/default')
2019-01-18 04:11:29 -05:00
app.config.version = config_api.config_api().getVersion()
2021-01-30 00:32:26 -05:00
2019-12-08 08:10:22 -05:00
cache = Cache(config={'CACHE_TYPE': 'simple'})
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
2019-02-18 03:21:31 -05:00
2018-12-25 10:48:29 -05:00
try:
from flask_sqlalchemy import SQLAlchemy
2019-02-21 22:47:56 -05:00
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/mw_session.db'
2018-12-25 10:48:29 -05:00
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SESSION_TYPE'] = 'sqlalchemy'
app.config['SESSION_SQLALCHEMY'] = sdb
app.config['SESSION_SQLALCHEMY_TABLE'] = 'session'
2019-02-21 22:47:56 -05:00
sdb = SQLAlchemy(app)
sdb.create_all()
2018-12-25 10:48:29 -05:00
except:
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = '/tmp/py_mw_session_' + \
str(sys.version_info[0])
app.config['SESSION_FILE_THRESHOLD'] = 1024
app.config['SESSION_FILE_MODE'] = 384
2020-07-10 03:57:25 -04:00
mw.execShell("pip install flask_sqlalchemy &")
2018-12-25 10:48:29 -05:00
2021-01-30 00:32:26 -05:00
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
2018-12-28 00:07:21 -05:00
app.config['SESSION_PERMANENT'] = True
2018-12-25 10:48:29 -05:00
app.config['SESSION_USE_SIGNER'] = True
app.config['SESSION_KEY_PREFIX'] = 'MW_:'
app.config['SESSION_COOKIE_NAME'] = "MW_VER_1"
2021-01-30 00:32:26 -05:00
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=31)
2021-11-03 11:56:47 -04:00
# Session(app)
2018-12-25 10:48:29 -05:00
2019-02-18 11:01:30 -05:00
# socketio
from flask_socketio import SocketIO, emit, send
socketio = SocketIO()
socketio.init_app(app)
2021-11-08 05:31:00 -05:00
# from gevent.pywsgi import WSGIServer
# from geventwebsocket.handler import WebSocketHandler
# http_server = WSGIServer(('0.0.0.0', '7200'), app,
# handler_class=WebSocketHandler)
# http_server.serve_forever()
2018-12-25 10:48:29 -05:00
2018-12-28 00:15:03 -05:00
# debug macosx dev
2020-07-10 03:57:25 -04:00
if mw.isAppleSystem():
2018-12-28 00:15:03 -05:00
app.debug = True
app.config.version = app.config.version + str(time.time())
2018-12-27 22:31:08 -05:00
import common
common.init()
2018-12-25 02:12:59 -05:00
def funConvert(fun):
block = fun.split('_')
func = block[0]
for x in range(len(block) - 1):
suf = block[x + 1].title()
func += suf
return func
2018-12-24 21:52:39 -05:00
2018-12-25 10:48:29 -05:00
def isLogined():
2021-01-30 00:56:08 -05:00
# print('isLogined', session)
2018-12-27 10:16:12 -05:00
if 'login' in session and 'username' in session and session['login'] == True:
2022-06-11 11:48:05 -04:00
userInfo = mw.M('users').where(
"id=?", (1,)).field('id,username,password').find()
if userInfo['username'] != session['username']:
return False
2022-06-11 12:06:54 -04:00
now_time = int(time.time())
2022-06-12 13:02:29 -04:00
if 'overdue' in session and now_time > session['overdue']:
2022-06-11 12:06:54 -04:00
# 自动续期
session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60
return False
2018-12-25 10:48:29 -05:00
return True
2021-01-30 01:54:37 -05:00
if os.path.exists('data/api_login.txt'):
content = mw.readFile('data/api_login.txt')
session['login'] = True
session['username'] = content
os.remove('data/api_login.txt')
2018-12-25 10:48:29 -05:00
return False
2018-12-25 01:30:51 -05:00
def publicObject(toObject, func, action=None, get=None):
2018-12-25 02:41:46 -05:00
name = funConvert(func) + 'Api'
2019-02-17 01:42:51 -05:00
try:
if hasattr(toObject, name):
efunc = 'toObject.' + name + '()'
data = eval(efunc)
return data
2022-03-23 03:45:38 -04:00
data = {'msg': '404,not find api[' + name + ']', "status": False}
return mw.getJson(data)
2019-02-17 01:42:51 -05:00
except Exception as e:
data = {'msg': '访问异常:' + str(e) + '!', "status": False}
2020-07-10 03:57:25 -04:00
return mw.getJson(data)
2018-12-25 01:30:51 -05:00
2018-12-25 02:41:46 -05:00
2018-12-25 04:43:28 -05:00
@app.route("/test")
def test():
2021-04-30 23:31:51 -04:00
print(sys.version_info)
print(session)
2020-07-10 03:57:25 -04:00
os = mw.getOs()
2021-04-30 23:31:51 -04:00
print(os)
2020-07-10 03:57:25 -04:00
return mw.getLocalIp()
2018-12-25 04:43:28 -05:00
2019-02-21 10:05:09 -05:00
@app.route('/close')
def close():
if not os.path.exists('data/close.pl'):
return redirect('/')
data = {}
2020-07-10 03:57:25 -04:00
data['cmd'] = 'rm -rf ' + mw.getRunDir() + '/data/close.pl'
2019-02-21 10:05:09 -05:00
return render_template('close.html', data=data)
2018-12-25 04:43:28 -05:00
@app.route("/code")
def code():
import vilidate
vie = vilidate.vieCode()
codeImage = vie.GetCodeImage(80, 4)
2021-05-01 02:17:42 -04:00
# try:
# from cStringIO import StringIO
# except:
# from StringIO import StringIO
2018-12-25 04:43:28 -05:00
2021-05-01 02:17:42 -04:00
out = io.BytesIO()
2018-12-25 04:43:28 -05:00
codeImage[0].save(out, "png")
2021-05-09 10:48:23 -04:00
# print(codeImage[1])
2021-05-01 02:17:42 -04:00
2020-07-10 03:57:25 -04:00
session['code'] = mw.md5(''.join(codeImage[1]).lower())
2018-12-25 04:43:28 -05:00
img = Response(out.getvalue(), headers={'Content-Type': 'image/png'})
return make_response(img)
@app.route("/check_login", methods=['POST'])
2018-12-25 02:41:46 -05:00
def checkLogin():
2018-12-27 04:22:11 -05:00
if isLogined():
return "true"
return "false"
2018-12-25 01:30:51 -05:00
2018-12-25 04:43:28 -05:00
@app.route("/login")
def login():
2018-12-27 04:22:11 -05:00
dologin = request.args.get('dologin', '')
if dologin == 'True':
session.clear()
2018-12-27 22:40:21 -05:00
return redirect('/login')
2018-12-27 04:22:11 -05:00
2018-12-25 10:48:29 -05:00
if isLogined():
return redirect('/')
2018-12-25 04:43:28 -05:00
return render_template('login.html')
@app.route("/do_login", methods=['POST'])
def doLogin():
username = request.form.get('username', '').strip()
password = request.form.get('password', '').strip()
code = request.form.get('code', '').strip()
2021-05-09 10:50:27 -04:00
# print(session)
if 'code' in session:
if session['code'] != mw.md5(code):
return mw.returnJson(False, '验证码错误,请重新输入!')
2018-12-25 04:43:28 -05:00
2020-07-10 03:57:25 -04:00
userInfo = mw.M('users').where(
2018-12-25 04:43:28 -05:00
"id=?", (1,)).field('id,username,password').find()
2021-05-09 10:50:27 -04:00
# print(userInfo)
# print(password)
2021-05-01 02:17:42 -04:00
2020-07-10 03:57:25 -04:00
password = mw.md5(password)
2021-05-01 02:17:42 -04:00
2021-05-09 10:50:27 -04:00
# print('md5-pass', password)
2021-05-01 02:17:42 -04:00
2019-12-08 08:10:22 -05:00
login_cache_count = 5
login_cache_limit = cache.get('login_cache_limit')
filename = 'data/close.pl'
if os.path.exists(filename):
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '面板已经关闭!')
2019-12-08 08:10:22 -05:00
2018-12-25 04:43:28 -05:00
if userInfo['username'] != username or userInfo['password'] != password:
2019-12-08 08:10:22 -05:00
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:
2020-07-10 03:57:25 -04:00
mw.writeFile(filename, 'True')
return mw.returnJson(False, '面板已经关闭!')
2019-12-08 08:10:22 -05:00
cache.set('login_cache_limit', login_cache_limit, timeout=10000)
login_cache_limit = cache.get('login_cache_limit')
2020-07-10 03:57:25 -04:00
mw.writeLog('用户登录', mw.getInfo(msg))
return mw.returnJson(False, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit))))
2018-12-25 04:43:28 -05:00
2019-12-08 08:10:22 -05:00
cache.delete('login_cache_limit')
2018-12-25 04:43:28 -05:00
session['login'] = True
session['username'] = userInfo['username']
2022-06-11 12:06:54 -04:00
session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60
# session['overdue'] = int(time.time()) + 7
2021-01-30 01:54:37 -05:00
# fix 跳转时,数据消失,可能是跨域问题
mw.writeFile('data/api_login.txt', userInfo['username'])
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '登录成功,正在跳转...')
2018-12-25 04:43:28 -05:00
2022-03-23 03:45:38 -04:00
@app.errorhandler(404)
2022-03-23 03:30:28 -04:00
def page_unauthorized(error):
2022-03-23 03:45:38 -04:00
return render_template_string('404 not found', error_info=error), 404
2022-03-23 03:30:28 -04:00
2018-12-24 21:52:39 -05:00
@app.route('/<reqClass>/<reqAction>', methods=['POST', 'GET'])
@app.route('/<reqClass>/', methods=['POST', 'GET'])
@app.route('/<reqClass>', methods=['POST', 'GET'])
@app.route('/', methods=['POST', 'GET'])
def index(reqClass=None, reqAction=None, reqData=None):
comReturn = common.local()
if comReturn:
return comReturn
2018-12-24 21:52:39 -05:00
if (reqClass == None):
reqClass = 'index'
2021-11-14 06:34:57 -05:00
pageFile = ('config', 'control', 'crontab', 'files', 'firewall',
'index', 'plugins', 'login', 'system', 'site', 'ssl', 'task', 'soft')
if not reqClass in pageFile:
2022-03-23 03:45:38 -04:00
return redirect('/')
2018-12-24 21:52:39 -05:00
if reqAction == None:
2018-12-25 10:48:29 -05:00
if not isLogined():
return redirect('/login')
2019-01-02 00:29:29 -05:00
2019-01-02 03:27:18 -05:00
import config_api
data = config_api.config_api().get()
return render_template(reqClass + '.html', data=data)
2018-12-24 22:21:20 -05:00
2021-11-14 06:34:57 -05:00
classFile = ('config_api', 'crontab_api', 'files_api', 'firewall_api',
'plugins_api', 'system_api', 'site_api', 'task_api')
2018-12-24 22:21:20 -05:00
className = reqClass + '_api'
2021-11-14 06:34:57 -05:00
if not className in classFile:
return "error"
2018-12-24 22:21:20 -05:00
2018-12-24 22:26:46 -05:00
eval_str = "__import__('" + className + "')." + className + '()'
newInstance = eval(eval_str)
2021-11-14 06:34:57 -05:00
2018-12-25 01:30:51 -05:00
return publicObject(newInstance, reqAction)
2019-02-18 03:21:31 -05:00
ssh = None
shell = None
try:
import paramiko
ssh = paramiko.SSHClient()
except:
2021-05-09 10:50:27 -04:00
mw.execShell('pip3 install paramiko &')
2019-02-18 03:21:31 -05:00
2019-02-19 00:12:01 -05:00
def create_rsa():
2020-07-10 03:57:25 -04:00
mw.execShell("rm -f /root/.ssh/*")
mw.execShell('ssh-keygen -q -t rsa -P "" -f /root/.ssh/id_rsa')
mw.execShell('cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys')
mw.execShell('chmod 600 /root/.ssh/authorized_keys')
2019-02-19 00:12:01 -05:00
2019-03-02 21:57:39 -05:00
def clear_ssh():
sh = '''
#!/bin/bash
PLIST=`who | grep localhost | awk '{print $2}'`
for i in $PLIST
do
2019-03-14 00:58:28 -04:00
ps -t /dev/$i |grep -v TTY |awk '{print $1}' | xargs kill -9
2019-03-02 21:57:39 -05:00
done
'''
2020-07-10 03:57:25 -04:00
if not mw.isAppleSystem():
info = mw.execShell(sh)
2021-04-30 23:45:29 -04:00
print(info[0], info[1])
2019-03-02 21:57:39 -05:00
2019-02-18 03:21:31 -05:00
def connect_ssh():
2019-03-14 00:58:28 -04:00
# print 'connect_ssh ....'
2019-03-02 21:57:39 -05:00
clear_ssh()
2019-02-18 03:21:31 -05:00
global shell, ssh
2019-02-19 00:12:01 -05:00
if not os.path.exists('/root/.ssh/authorized_keys') or not os.path.exists('/root/.ssh/id_rsa') or not os.path.exists('/root/.ssh/id_rsa.pub'):
create_rsa()
2019-02-18 05:20:57 -05:00
2019-02-18 03:21:31 -05:00
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
2020-07-10 03:57:25 -04:00
ssh.connect('localhost', mw.getSSHPort())
2019-02-18 03:21:31 -05:00
except Exception as e:
2020-07-10 03:57:25 -04:00
if mw.getSSHStatus():
2019-02-18 03:21:31 -05:00
try:
2020-07-10 03:57:25 -04:00
ssh.connect('127.0.0.1', mw.getSSHPort())
2019-02-18 03:21:31 -05:00
except:
return False
2020-07-10 03:57:25 -04:00
ssh.connect('127.0.0.1', mw.getSSHPort())
2019-02-19 00:25:31 -05:00
shell = ssh.invoke_shell(term='xterm', width=83, height=21)
2019-02-18 03:21:31 -05:00
shell.setblocking(0)
return True
# 取数据对象
def get_input_data(data):
pdata = common.dict_obj()
for key in data.keys():
pdata[key] = str(data[key])
return pdata
@socketio.on('webssh')
def webssh(msg):
2021-11-08 05:39:21 -05:00
# print('webssh ...')
2019-02-18 03:21:31 -05:00
if not isLogined():
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
return None
global shell, ssh
ssh_success = True
if not shell:
ssh_success = connect_ssh()
if not shell:
2019-02-19 00:12:01 -05:00
emit('server_response', {'data': '连接SSH服务失败!\r\n'})
2019-02-18 03:21:31 -05:00
return
if shell.exit_status_ready():
ssh_success = connect_ssh()
if not ssh_success:
2019-02-19 00:12:01 -05:00
emit('server_response', {'data': '连接SSH服务失败!\r\n'})
2019-02-18 03:21:31 -05:00
return
shell.send(msg)
try:
time.sleep(0.005)
recv = shell.recv(4096)
emit('server_response', {'data': recv.decode("utf-8")})
except Exception as ex:
2019-03-14 00:58:28 -04:00
pass
# print 'webssh:' + str(ex)
2019-02-18 03:21:31 -05:00
@socketio.on('connect_event')
def connected_msg(msg):
if not isLogined():
2019-08-01 20:30:14 -04:00
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
2019-02-18 03:21:31 -05:00
return None
global shell, ssh
2019-03-14 00:56:03 -04:00
ssh_success = True
if not shell:
ssh_success = connect_ssh()
if not ssh_success:
emit('server_response', {'data': '连接SSH服务失败!\r\n'})
return
2019-02-18 03:21:31 -05:00
try:
recv = shell.recv(8192)
2019-02-19 01:03:14 -05:00
# print recv.decode("utf-8")
2019-02-18 03:21:31 -05:00
emit('server_response', {'data': recv.decode("utf-8")})
except Exception as e:
2019-03-14 00:58:28 -04:00
pass
# print 'connected_msg:' + str(e)
2019-02-18 03:21:31 -05:00
2019-03-13 23:31:00 -04:00
# @socketio.on('panel')
# def websocket_test(data):
# pdata = get_input_data(data)
# if not isLogined():
# emit(pdata.s_response, {
2020-07-10 03:57:25 -04:00
# 'data': mw.returnData(-1, '会话丢失,请重新登陆面板!\r\n')})
2019-03-13 23:31:00 -04:00
# return None
# mods = ['site', 'ftp', 'database', 'ajax', 'system', 'crontab', 'files',
# 'config', 'panel_data', 'plugin', 'ssl', 'auth', 'firewall', 'panel_wxapp']
# if not pdata['s_module'] in mods:
# result = '指定模块不存在!'
# else:
# result = eval("%s(pdata)" % pdata['s_module'])
# if not hasattr(pdata, 's_response'):
# pdata.s_response = 'response'
# emit(pdata.s_response, {'data': result})