mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
1. Added Mail Marketing Automation trigger tasks 2. Added Mail Marketing Groups Import, Export, Merge 3. Added Mail Marketing Subscribers to support paste import 4. Added Mail Marketing Template Import Export Duplicate 5. Added Mail server add timed automatic reply 6. Added HTTPS Protection function for Website (disables automatic HTTP to HTTPS redirection when enabled) 7. Optimize Website Interface Button Integration 8. Optimize the response speed of WP Toolkit interface
429 lines
13 KiB
Python
429 lines
13 KiB
Python
#coding: utf-8
|
|
#-------------------------------------------------------------------
|
|
# aaPanel
|
|
#-------------------------------------------------------------------
|
|
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
|
#-------------------------------------------------------------------
|
|
# Author: hwliang <hwl@aapanel.com>
|
|
#-------------------------------------------------------------------
|
|
|
|
# sqlite模型
|
|
#------------------------------
|
|
import os,re,json,shutil,time
|
|
from databaseModel.base import databaseBase
|
|
import public
|
|
try:
|
|
import redis
|
|
except:
|
|
public.ExecShell("btpip install redis")
|
|
import redis
|
|
try:
|
|
from BTPanel import session
|
|
except :pass
|
|
|
|
|
|
class panelRedisDB():
|
|
|
|
__DB_PASS = None
|
|
__DB_USER = None
|
|
__DB_PORT = 6379
|
|
__DB_HOST = '127.0.0.1'
|
|
__DB_CONN = None
|
|
__DB_ERR = None
|
|
|
|
__DB_CLOUD = None
|
|
def __init__(self):
|
|
self.__config = self.get_options(None)
|
|
|
|
def redis_conn(self,db_idx = 0):
|
|
|
|
if self.__DB_HOST in ['127.0.0.1','localhost']:
|
|
if not os.path.exists('/www/server/redis'): return False
|
|
|
|
if not self.__DB_CLOUD:
|
|
self.__DB_PASS = self.__config['requirepass']
|
|
self.__DB_PORT = int(self.__config['port'])
|
|
|
|
try:
|
|
redis_pool = redis.ConnectionPool(host=self.__DB_HOST, port= self.__DB_PORT, password= self.__DB_PASS, db= db_idx)
|
|
self.__DB_CONN = redis.Redis(connection_pool= redis_pool)
|
|
return self.__DB_CONN
|
|
except :
|
|
self.__DB_ERR = public.get_error_info()
|
|
return False
|
|
|
|
|
|
def set_host(self,host,port,name,username,password,prefix = ''):
|
|
self.__DB_HOST = host
|
|
self.__DB_PORT = int(port)
|
|
self.__DB_NAME = name
|
|
if self.__DB_NAME: self.__DB_NAME = str(self.__DB_NAME)
|
|
self.__DB_USER = str(username)
|
|
self._USER = str(username)
|
|
self.__DB_PASS = str(password)
|
|
self.__DB_PREFIX = prefix
|
|
self.__DB_CLOUD = 1
|
|
return self
|
|
|
|
|
|
#获取配置项
|
|
def get_options(self,get = None):
|
|
|
|
result = {}
|
|
redis_conf = public.readFile("{}/redis/redis.conf".format(public.get_setup_path()))
|
|
if not redis_conf: return False
|
|
|
|
keys = ["bind","port","timeout","maxclients","databases","requirepass","maxmemory"]
|
|
for k in keys:
|
|
v = ""
|
|
rep = "\n%s\\s+(.+)" % k
|
|
group = re.search(rep,redis_conf)
|
|
if not group:
|
|
if k == "maxmemory":
|
|
v = "0"
|
|
if k == "maxclients":
|
|
v = "10000"
|
|
if k == "requirepass":
|
|
v = ""
|
|
else:
|
|
if k == "maxmemory":
|
|
v = int(group.group(1)) / 1024 / 1024
|
|
else:
|
|
v = group.group(1)
|
|
result[k] = v
|
|
return result
|
|
|
|
|
|
|
|
class main(databaseBase):
|
|
|
|
_db_max = 16 #最大redis数据库
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
|
|
def GetCloudServer(self,args):
|
|
'''
|
|
@name 获取远程服务器列表
|
|
@author hwliang<2021-01-10>
|
|
@return list
|
|
'''
|
|
return self.GetBaseCloudServer(args)
|
|
# return public.return_message(0, 0, self.GetBaseCloudServer(args))
|
|
|
|
|
|
def AddCloudServer(self,args):
|
|
'''
|
|
@添加远程数据库
|
|
'''
|
|
return self.AddBaseCloudServer(args)
|
|
|
|
def RemoveCloudServer(self,args):
|
|
'''
|
|
@删除远程数据库
|
|
'''
|
|
return self.RemoveBaseCloudServer(args)
|
|
|
|
def ModifyCloudServer(self,args):
|
|
'''
|
|
@修改远程数据库
|
|
'''
|
|
return self.ModifyBaseCloudServer(args)
|
|
|
|
def get_obj_by_sid(self,sid = 0,conn_config = None):
|
|
"""
|
|
@取mssql数据库对像 By sid
|
|
@sid 数据库分类,0:本地
|
|
"""
|
|
if type(sid) == str:
|
|
try:
|
|
sid = int(sid)
|
|
except :sid = 0
|
|
|
|
if sid:
|
|
if not conn_config: conn_config = public.M('database_servers').where("id=?" ,sid).find()
|
|
db_obj = panelRedisDB()
|
|
|
|
try:
|
|
db_obj = db_obj.set_host(conn_config['db_host'],conn_config['db_port'],None,conn_config['db_user'],conn_config['db_password'])
|
|
except Exception as e:
|
|
raise public.PanelError(e)
|
|
else:
|
|
db_obj = panelRedisDB()
|
|
return db_obj
|
|
|
|
|
|
|
|
def get_list(self,args):
|
|
"""
|
|
@获取数据库列表
|
|
@sql_type = redis
|
|
"""
|
|
result = []
|
|
self.sid = args.get('sid/d',0)
|
|
for x in range(0,self._db_max):
|
|
|
|
data = {}
|
|
data['id'] = x
|
|
data['name'] = 'DB{}'.format(x)
|
|
|
|
|
|
try:
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(x)
|
|
|
|
data['keynum'] = redis_obj.dbsize()
|
|
if data['keynum'] > 0:
|
|
result.append(data)
|
|
except :pass
|
|
|
|
#result = sorted(result,key= lambda x:x['keynum'],reverse=True)
|
|
return result
|
|
|
|
|
|
def set_redis_val(self,args):
|
|
"""
|
|
@设置或修改指定值
|
|
"""
|
|
|
|
self.sid = args.get('sid/d',0)
|
|
if not 'name' in args or not 'val' in args:
|
|
return public.returnMsg(False, public.lang("Parameter passing error."));
|
|
|
|
endtime = 0
|
|
if 'endtime' in args : endtime = int(args.endtime)
|
|
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(args.db_idx)
|
|
if endtime:
|
|
redis_obj.set(args.name, args.val, endtime)
|
|
else:
|
|
redis_obj.set(args.name, args.val)
|
|
public.set_module_logs('linux_redis','set_redis_val',1)
|
|
return public.returnMsg(True, public.lang("Operation is successful."));
|
|
|
|
def del_redis_val(self,args):
|
|
"""
|
|
@删除key值
|
|
"""
|
|
self.sid = args.get('sid/d',0)
|
|
if not 'key' in args:
|
|
return public.returnMsg(False, public.lang("Parameter passing error."));
|
|
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(args.db_idx)
|
|
redis_obj.delete(args.key)
|
|
|
|
return public.returnMsg(True, public.lang("Operation is successful."));
|
|
|
|
|
|
def clear_flushdb(self,args):
|
|
"""
|
|
清空数据库
|
|
@ids 清空数据库列表,不传则清空所有
|
|
"""
|
|
self.sid = args.get('sid/d',0)
|
|
ids = json.loads(args.ids)
|
|
#ids = []
|
|
if len(ids) == 0:
|
|
for x in range(0,self._db_max):
|
|
ids.append(x)
|
|
|
|
for x in ids:
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(x)
|
|
redis_obj.flushdb()
|
|
|
|
return public.returnMsg(True, public.lang("Operation is successful."));
|
|
|
|
def get_db_keylist(self,args):
|
|
"""
|
|
@获取指定数据库key集合
|
|
"""
|
|
|
|
search = '*'
|
|
if 'search' in args: search = "*" + args.search+"*"
|
|
db_idx = args.db_idx
|
|
self.sid = args.get('sid/d',0)
|
|
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(db_idx)
|
|
try:
|
|
keylist = sorted(redis_obj.keys(search))
|
|
except :
|
|
keylist = []
|
|
|
|
|
|
info = {'p':1,'row':10,'count':len(keylist)}
|
|
|
|
if hasattr(args,'limit'): info['row'] = int(args.limit)
|
|
if hasattr(args,'p'): info['p'] = int(args['p'])
|
|
|
|
import page
|
|
#实例化分页类
|
|
page = page.Page();
|
|
|
|
info['uri'] = args
|
|
info['return_js'] = ''
|
|
if hasattr(args,'tojs'): info['return_js'] = args.tojs
|
|
|
|
slist = keylist[(info['p']-1) * info['row']:info['p'] * info['row']]
|
|
|
|
rdata = {}
|
|
rdata['page'] = page.GetPage(info,'1,2,3,4,5,8')
|
|
rdata['where'] = ''
|
|
rdata['data'] = []
|
|
|
|
idx = 0
|
|
for key in slist:
|
|
item = {}
|
|
try:
|
|
item['name'] = key.decode()
|
|
except:
|
|
item['name'] = str(key)
|
|
|
|
item['endtime'] = redis_obj.ttl(key)
|
|
if item['endtime'] == -1: item['endtime'] = 0
|
|
|
|
item['type'] = redis_obj.type(key).decode()
|
|
|
|
if item['type'] == 'string':
|
|
try:
|
|
item['val'] = redis_obj.get(key).decode()
|
|
except:
|
|
item['val'] = str(redis_obj.get(key))
|
|
elif item['type'] == 'hash':
|
|
item['val'] = str(redis_obj.hgetall(key))
|
|
elif item['type'] == 'list':
|
|
item['val'] = str(redis_obj.lrange(key, 0, -1))
|
|
elif item['type'] == 'set':
|
|
item['val'] = str(redis_obj.smembers(key))
|
|
elif item['type'] == 'zset':
|
|
item['val'] = str(redis_obj.zrange(key, 0, 1, withscores=True))
|
|
else:
|
|
item['val'] = ''
|
|
try:
|
|
item['len'] = redis_obj.strlen(key)
|
|
except:
|
|
item['len'] = len(item['val'])
|
|
item['val'] = public.xsssec(item['val'])
|
|
item['name'] = public.xsssec(item['name'])
|
|
rdata['data'].append(item)
|
|
idx += 1
|
|
return rdata
|
|
|
|
|
|
def ToBackup(self,args):
|
|
"""
|
|
@备份数据库
|
|
"""
|
|
|
|
self.sid = args.get('sid/d',0)
|
|
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(0)
|
|
redis_obj.save()
|
|
|
|
src_path = '{}/dump.rdb'.format(redis_obj.config_get()['dir'])
|
|
if not os.path.exists(src_path):
|
|
return public.returnMsg(False, public.lang("Backup error"));
|
|
|
|
backup_path = session['config']['backup_path'] + '/database/redis/'
|
|
if not os.path.exists(backup_path): os.makedirs(backup_path)
|
|
|
|
fileName = backup_path + str(self.sid) + '_db_' + time.strftime('%Y%m%d_%H%M%S',time.localtime()) +'.rdb'
|
|
|
|
shutil.copyfile(src_path,fileName)
|
|
if not os.path.exists(fileName):
|
|
return public.returnMsg(False, public.lang("Backup error"));
|
|
|
|
return public.returnMsg(True, public.lang("Backup Succeeded!"))
|
|
|
|
def DelBackup(self,args):
|
|
"""
|
|
@删除备份文件
|
|
"""
|
|
file = args.file
|
|
if os.path.exists(file): os.remove(file)
|
|
|
|
return public.returnMsg(True, public.lang("Delete successfully!"));
|
|
|
|
def InputSql(self,get):
|
|
"""
|
|
@导入数据库
|
|
"""
|
|
file = get.file
|
|
self.sid = get.get('sid/d',0)
|
|
|
|
redis_obj = self.get_obj_by_sid(self.sid).redis_conn(0)
|
|
|
|
rpath = redis_obj.config_get()['dir']
|
|
dst_path = '{}/dump.rdb'.format(rpath)
|
|
public.ExecShell("/etc/init.d/redis stop")
|
|
if os.path.exists(dst_path): os.remove(dst_path)
|
|
shutil.copy2(file, dst_path)
|
|
public.ExecShell("chown redis.redis {dump} && chmod 644 {dump}".format(dump=dst_path))
|
|
# self.restart_services()
|
|
public.ExecShell("/etc/init.d/redis start")
|
|
if os.path.exists(dst_path):
|
|
return public.returnMsg(True, public.lang("Restore Successful."))
|
|
return public.returnMsg(False, public.lang("Restore failure."))
|
|
|
|
|
|
def get_backup_list(self,get):
|
|
"""
|
|
@获取备份文件列表
|
|
"""
|
|
search = ''
|
|
if hasattr(get,'search'): search = get['search'].strip().lower();
|
|
|
|
|
|
nlist = []
|
|
cloud_list = {}
|
|
for x in self.GetCloudServer({'type':'redis'}):
|
|
cloud_list['id-' + str(x['id'])] = x
|
|
|
|
path = session['config']['backup_path'] + '/database/redis/'
|
|
if not os.path.exists(path): os.makedirs(path)
|
|
for name in os.listdir(path):
|
|
if search:
|
|
if name.lower().find(search) == -1: continue;
|
|
|
|
arrs = name.split('_')
|
|
|
|
filepath = '{}/{}'.format(path,name).replace('//','/')
|
|
stat = os.stat(filepath)
|
|
|
|
item = {}
|
|
item['name'] = name
|
|
item['filepath'] = filepath
|
|
item['size'] = stat.st_size
|
|
item['mtime'] = int(stat.st_mtime)
|
|
item['sid'] = arrs[0]
|
|
item['conn_config'] = cloud_list['id-' + str(arrs[0])]
|
|
|
|
nlist.append(item)
|
|
if hasattr(get, 'sort'):
|
|
nlist = sorted(nlist, key=lambda data: data['mtime'], reverse=get["sort"] == "desc")
|
|
return nlist
|
|
|
|
|
|
|
|
def restart_services(self):
|
|
"""
|
|
@重启服务
|
|
"""
|
|
public.ExecShell('net stop redis')
|
|
public.ExecShell('net start redis')
|
|
return True
|
|
|
|
|
|
def check_cloud_database_status(self,conn_config):
|
|
"""
|
|
@检测远程数据库是否连接
|
|
@conn_config 远程数据库配置,包含host port pwd等信息
|
|
"""
|
|
try:
|
|
|
|
sql_obj = panelRedisDB().set_host(conn_config['db_host'],conn_config['db_port'],conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
|
|
keynum = sql_obj.redis_conn(0).dbsize()
|
|
return True
|
|
except Exception as ex:
|
|
|
|
return public.returnMsg(False,ex)
|