mdserver-web/class/core/config_api.py

335 lines
12 KiB
Python
Raw Normal View History

2018-12-28 23:42:29 -05:00
# coding: utf-8
import psutil
import time
import os
import sys
2020-07-10 03:57:25 -04:00
import mw
2018-12-28 23:42:29 -05:00
import re
import json
import pwd
2019-01-09 11:52:03 -05:00
from flask import session
from flask import request
2018-12-28 23:42:29 -05:00
class config_api:
2019-03-15 02:52:18 -04:00
# 本版解决自启动问题
2019-03-25 09:42:49 -04:00
# 文件管理重命名
# 优化计划任务管理
2021-11-12 06:52:39 -05:00
__version = '0.8.6'
2019-11-30 08:41:03 -05:00
2018-12-28 23:42:29 -05:00
def __init__(self):
pass
##### ----- start ----- ###
2019-01-18 04:11:29 -05:00
2019-02-22 05:00:39 -05:00
# 取面板列表
def getPanelListApi(self):
2020-07-10 03:57:25 -04:00
data = mw.M('panel').field(
2019-02-22 05:00:39 -05:00
'id,title,url,username,password,click,addtime').order('click desc').select()
2020-07-10 03:57:25 -04:00
return mw.getJson(data)
2019-02-22 05:00:39 -05:00
def addPanelInfoApi(self):
title = request.form.get('title', '')
url = request.form.get('url', '')
username = request.form.get('username', '')
password = request.form.get('password', '')
# 校验是还是重复
2020-07-10 03:57:25 -04:00
isAdd = mw.M('panel').where(
2019-02-22 05:00:39 -05:00
'title=? OR url=?', (title, url)).count()
if isAdd:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '备注或面板地址重复!')
isRe = mw.M('panel').add('title,url,username,password,click,addtime',
(title, url, username, password, 0, int(time.time())))
2019-02-22 05:00:39 -05:00
if isRe:
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '添加成功!')
return mw.returnJson(False, '添加失败!')
2019-02-22 05:00:39 -05:00
# 删除面板资料
def delPanelInfoApi(self):
mid = request.form.get('id', '')
2020-07-10 03:57:25 -04:00
isExists = mw.M('panel').where('id=?', (mid,)).count()
2019-02-22 05:00:39 -05:00
if not isExists:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '指定面板资料不存在!')
mw.M('panel').where('id=?', (mid,)).delete()
return mw.returnJson(True, '删除成功!')
2019-02-22 05:00:39 -05:00
2019-02-22 05:04:42 -05:00
# 修改面板资料
def setPanelInfoApi(self):
title = request.form.get('title', '')
url = request.form.get('url', '')
username = request.form.get('username', '')
password = request.form.get('password', '')
mid = request.form.get('id', '')
# 校验是还是重复
2020-07-10 03:57:25 -04:00
isSave = mw.M('panel').where(
2019-02-22 05:04:42 -05:00
'(title=? OR url=?) AND id!=?', (title, url, mid)).count()
if isSave:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '备注或面板地址重复!')
2019-02-22 05:04:42 -05:00
# 更新到数据库
2020-07-10 03:57:25 -04:00
isRe = mw.M('panel').where('id=?', (mid,)).save(
2019-02-22 05:04:42 -05:00
'title,url,username,password', (title, url, username, password))
if isRe:
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '修改成功!')
return mw.returnJson(False, '修改失败!')
2019-02-22 05:04:42 -05:00
2019-01-09 11:52:03 -05:00
def syncDateApi(self):
2020-07-10 03:57:25 -04:00
if mw.isAppleSystem():
return mw.returnJson(True, '开发系统不必同步时间!')
2019-01-09 11:52:03 -05:00
2020-07-10 03:57:25 -04:00
data = mw.execShell('ntpdate -s time.nist.gov')
2019-01-09 11:52:03 -05:00
if data[0] == '':
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '同步成功!')
return mw.returnJson(False, '同步失败:' + data[0])
2019-01-09 11:52:03 -05:00
def setPasswordApi(self):
password1 = request.form.get('password1', '')
password2 = request.form.get('password2', '')
if password1 != password2:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '两次输入的密码不一致,请重新输入!')
2019-01-09 11:52:03 -05:00
if len(password1) < 5:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '用户密码不能小于5位!')
mw.M('users').where("username=?", (session['username'],)).setField(
'password', mw.md5(password1.strip()))
return mw.returnJson(True, '密码修改成功!')
2019-01-09 11:52:03 -05:00
def setNameApi(self):
name1 = request.form.get('name1', '')
name2 = request.form.get('name2', '')
if name1 != name2:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '两次输入的用户名不一致,请重新输入!')
2019-01-09 11:52:03 -05:00
if len(name1) < 3:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '用户名长度不能少于3位')
2019-01-09 11:52:03 -05:00
2020-07-10 03:57:25 -04:00
mw.M('users').where("username=?", (session['username'],)).setField(
2019-01-09 11:52:03 -05:00
'username', name1.strip())
session['username'] = name1
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '用户修改成功!')
2019-01-09 11:52:03 -05:00
2019-01-18 02:46:59 -05:00
def setApi(self):
webname = request.form.get('webname', '')
port = request.form.get('port', '')
host_ip = request.form.get('host_ip', '')
domain = request.form.get('domain', '')
2019-01-18 03:05:21 -05:00
sites_path = request.form.get('sites_path', '')
backup_path = request.form.get('backup_path', '')
2019-01-18 02:46:59 -05:00
if domain != '':
reg = "^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
if not re.match(reg, domain):
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '主域名格式不正确')
2019-01-18 02:46:59 -05:00
if int(port) >= 65535 or int(port) < 100:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '端口范围不正确!')
2019-01-18 02:46:59 -05:00
2020-07-10 03:57:25 -04:00
if webname != mw.getConfig('title'):
mw.setConfig('title', webname)
2019-01-18 02:46:59 -05:00
2020-07-10 03:57:25 -04:00
if sites_path != mw.getWwwDir():
mw.setWwwDir(sites_path)
2019-01-18 03:05:21 -05:00
2020-07-10 03:57:25 -04:00
if backup_path != mw.getWwwDir():
mw.setBackupDir(backup_path)
2019-01-18 03:05:21 -05:00
2020-07-10 03:57:25 -04:00
if port != mw.getHostPort():
2019-01-18 02:46:59 -05:00
import system_api
2022-06-12 12:16:28 -04:00
import firewall_api
2020-07-10 03:57:25 -04:00
mw.setHostPort(port)
2022-06-12 12:16:28 -04:00
msg = mw.getInfo('放行端口[{1}]成功', (port,))
mw.writeLog("防火墙管理", msg)
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
2022-06-12 12:24:50 -04:00
mw.M('firewall').add('port,ps,addtime', (port, "配置修改", addtime))
2022-06-12 12:16:28 -04:00
firewall_api.firewall_api().addAcceptPort(port)
firewall_api.firewall_api().firewallReload()
2019-01-18 02:46:59 -05:00
system_api.system_api().restartMw()
2020-07-10 03:57:25 -04:00
if host_ip != mw.getHostAddr():
mw.setHostAddr(host_ip)
2019-01-18 02:46:59 -05:00
2020-07-10 03:57:25 -04:00
mhost = mw.getHostAddr()
2019-01-18 02:46:59 -05:00
info = {
'uri': '/config',
'host': mhost + ':' + port
}
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '保存成功!', info)
2019-01-18 02:46:59 -05:00
2019-02-21 06:13:39 -05:00
def setAdminPathApi(self):
admin_path = request.form.get('admin_path', '').strip()
2019-02-22 07:56:34 -05:00
admin_path_checks = ['/', '/close', '/login', '/do_login', '/site',
'/sites', '/download_file', '/control', '/crontab',
'/firewall', '/files', 'config', '/soft', '/system',
'/code', '/ssl', '/plugins']
2019-02-21 06:13:39 -05:00
if admin_path == '':
admin_path = '/'
if admin_path != '/':
if len(admin_path) < 6:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '安全入口地址长度不能小于6位!')
2019-02-21 06:13:39 -05:00
if admin_path in admin_path_checks:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '该入口已被面板占用,请使用其它入口!')
2019-02-21 06:13:39 -05:00
if not re.match("^/[\w\./-_]+$", admin_path):
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '入口地址格式不正确,示例: /my_panel')
2019-02-21 06:13:39 -05:00
else:
2020-07-10 03:57:25 -04:00
domain = mw.readFile('data/domain.conf')
2019-02-21 06:13:39 -05:00
if not domain:
domain = ''
2020-07-10 03:57:25 -04:00
limitip = mw.readFile('data/limitip.conf')
2019-02-21 06:13:39 -05:00
if not limitip:
limitip = ''
if not domain.strip() and not limitip.strip():
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '警告,关闭安全入口等于直接暴露你的后台地址在外网,十分危险,至少开启以下一种安全方式才能关闭:<a style="color:red;"><br>1、绑定访问域名<br>2、绑定授权IP</a>')
2019-02-21 06:13:39 -05:00
admin_path_file = 'data/admin_path.pl'
admin_path_old = '/'
if os.path.exists(admin_path_file):
2020-07-10 03:57:25 -04:00
admin_path_old = mw.readFile(admin_path_file).strip()
2019-02-21 06:13:39 -05:00
if admin_path_old != admin_path:
2020-07-10 03:57:25 -04:00
mw.writeFile(admin_path_file, admin_path)
mw.restartMw()
return mw.returnJson(True, '修改成功!')
2019-02-21 06:13:39 -05:00
2019-02-21 06:19:55 -05:00
def closePanelApi(self):
filename = 'data/close.pl'
if os.path.exists(filename):
os.remove(filename)
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, '开启成功')
mw.writeFile(filename, 'True')
mw.execShell("chmod 600 " + filename)
mw.execShell("chown root.root " + filename)
return mw.returnJson(True, '面板已关闭!')
2019-02-21 06:19:55 -05:00
def setIpv6StatusApi(self):
ipv6_file = 'data/ipv6.pl'
if os.path.exists('data/ipv6.pl'):
os.remove(ipv6_file)
2020-07-10 03:57:25 -04:00
mw.writeLog('面板设置', '关闭面板IPv6兼容!')
else:
2020-07-10 03:57:25 -04:00
mw.writeFile(ipv6_file, 'True')
mw.writeLog('面板设置', '开启面板IPv6兼容!')
mw.restartMw()
return mw.returnJson(True, '设置成功!')
# 获取面板证书
def getPanelSslApi(self):
cert = {}
2020-07-10 03:57:25 -04:00
cert['privateKey'] = mw.readFile('ssl/privateKey.pem')
cert['certPem'] = mw.readFile('ssl/certificate.pem')
cert['rep'] = os.path.exists('ssl/input.pl')
2020-07-10 03:57:25 -04:00
return mw.getJson(cert)
# 保存面板证书
def savePanelSslApi(self):
keyPath = 'ssl/privateKey.pem'
certPath = 'ssl/certificate.pem'
checkCert = '/tmp/cert.pl'
certPem = request.form.get('certPem', '').strip()
privateKey = request.form.get('privateKey', '').strip()
2020-07-10 03:57:25 -04:00
mw.writeFile(checkCert, certPem)
if privateKey:
2020-07-10 03:57:25 -04:00
mw.writeFile(keyPath, privateKey)
if certPem:
2020-07-10 03:57:25 -04:00
mw.writeFile(certPath, certPem)
if not mw.checkCert(checkCert):
return mw.returnJson(False, '证书错误,请检查!')
mw.writeFile('ssl/input.pl', 'True')
return mw.returnJson(True, '证书已保存!')
# 设置面板SSL
def setPanelSslApi(self):
2020-07-10 03:57:25 -04:00
sslConf = mw.getRunDir() + '/data/ssl.pl'
if os.path.exists(sslConf):
os.system('rm -f ' + sslConf)
2020-07-10 03:57:25 -04:00
return mw.returnJson(True, 'SSL已关闭请使用http协议访问面板!')
else:
os.system('pip install cffi==1.10')
os.system('pip install cryptography==2.1')
os.system('pip install pyOpenSSL==16.2')
try:
if not self.createSSL():
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '开启失败无法自动安装pyOpenSSL组件!<p>请尝试手动安装: pip install pyOpenSSL</p>')
mw.writeFile(sslConf, 'True')
except Exception as ex:
2020-07-10 03:57:25 -04:00
return mw.returnJson(False, '开启失败无法自动安装pyOpenSSL组件!<p>请尝试手动安装: pip install pyOpenSSL</p>')
return mw.returnJson(True, '开启成功请使用https协议访问面板!')
2019-02-21 10:05:09 -05:00
def getApi(self):
data = {}
2020-07-10 03:57:25 -04:00
return mw.getJson(data)
2019-01-09 11:52:03 -05:00
##### ----- end ----- ###
# 自签证书
def createSSL(self):
if os.path.exists('ssl/input.pl'):
return True
import OpenSSL
key = OpenSSL.crypto.PKey()
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
cert = OpenSSL.crypto.X509()
cert.set_serial_number(0)
2020-07-14 22:43:10 -04:00
cert.get_subject().CN = mw.getLocalIp()
cert.set_issuer(cert.get_subject())
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(86400 * 3650)
cert.set_pubkey(key)
cert.sign(key, 'md5')
cert_ca = OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert)
private_key = OpenSSL.crypto.dump_privatekey(
OpenSSL.crypto.FILETYPE_PEM, key)
if len(cert_ca) > 100 and len(private_key) > 100:
2020-07-10 03:57:25 -04:00
mw.writeFile('ssl/certificate.pem', cert_ca)
mw.writeFile('ssl/privateKey.pem', private_key)
2021-04-30 23:45:29 -04:00
print(cert_ca, private_key)
return True
return False
2019-01-18 04:11:29 -05:00
def getVersion(self):
return self.__version
2019-01-02 00:29:29 -05:00
def get(self):
data = {}
2020-07-10 03:57:25 -04:00
data['title'] = mw.getConfig('title')
data['site_path'] = mw.getWwwDir()
data['backup_path'] = mw.getBackupDir()
2019-01-09 11:52:03 -05:00
sformat = 'date +"%Y-%m-%d %H:%M:%S %Z %z"'
2020-07-10 03:57:25 -04:00
data['systemdate'] = mw.execShell(sformat)[0].strip()
2019-01-02 00:58:53 -05:00
2020-07-10 03:57:25 -04:00
data['port'] = mw.getHostPort()
data['ip'] = mw.getHostAddr()
2019-01-02 00:29:29 -05:00
2019-02-21 06:13:39 -05:00
admin_path_file = 'data/admin_path.pl'
if not os.path.exists(admin_path_file):
data['admin_path'] = '/'
else:
2020-07-10 03:57:25 -04:00
data['admin_path'] = mw.readFile(admin_path_file)
2019-02-21 06:13:39 -05:00
ipv6_file = 'data/ipv6.pl'
if os.path.exists('data/ipv6.pl'):
data['ipv6'] = 'checked'
else:
data['ipv6'] = ''
ssl_file = 'data/ssl.pl'
if os.path.exists('data/ssl.pl'):
data['ssl'] = 'checked'
else:
data['ssl'] = ''
2020-07-10 03:57:25 -04:00
data['site_count'] = mw.M('sites').count()
2019-02-25 04:10:32 -05:00
2020-07-10 03:57:25 -04:00
data['username'] = mw.M('users').where(
2019-01-09 11:52:03 -05:00
"id=?", (1,)).getField('username')
2019-01-02 00:29:29 -05:00
return data