Update to 7.7.0

Since version 7.7.0, we recommend yours update python to 3.12.

[+] Using nginx technology to load static files improves access speed
[+] Refactor homepage, website, FTP, and database using vue3
[+] Table loading changed to skeleton screen
[+] Add Website statistics-v2 professional plug-in
[+] Add Home page - top 5 resource occupancy
[+] Add protection for Files management (requires Tamper-proof for Enterprise 3.7)
[+] Website, FTP, Databases page add program status
[+] Add FTP log analysis (only supports Centos)
[+] Add password-free login to phpMyAdmin
[+] Add Proxy Project in Website (Supported when web service uses Nginx)
[+] Add WP Toolkit (Pro version only)
[+] Redesigned Docker module
[+] Add WP Toolkit Protection
[+] Add WP Toolkit Backup and Restore
[+] Add WP Toolkit Migrated
[+] Add WP Toolkit Clone site (supports new domain and subdomain)
[+] Add WP Toolkit Create site from backup of other panel
[+] Add WP Toolkit support for Cron automatic backup (only save Local disk)
[+] Add WP Toolkit operation log
[+] Add Integrity check for WP Toolkit
[+] Add WP Toolkit plug-in management and themes management

[*] Optimize phpMyAdmin formula access method
[*] Optimize Home page PHP display problem
[*] Optimize jump to the login interface after the login expires
[*] Optimize automatic renewal of SSL at some times
[*] Optimize Let's Encrypt to increase application success rate

[-] Fix Logs Audit cannot be opened
[-] Fix apache URL rewrite issue
[-] Fix phpmyadmin installation problem
[-] Fix the problem that some servers cannot install software
[-] Fix upload file error
[-] Fix left menu hiding problem
[-] Fix aaPanel Mobile QR code display problem
[-] Fix problem that third-party plug-ins are not displayed in the App Store
[-] Fix issue where the menu bar is blank when opening new tabs
[-] Fixed panel not being accessible in some cases
[-] Fix the issue where Curl warning caused the inability to apply for SSL
[-] Fix Quota issues for Website, FTP, Databases
[-] Fix file interface display problem on mobile terminal
This commit is contained in:
Jack
2024-07-19 11:25:10 +08:00
parent ed34994f45
commit ed55fa708d
1949 changed files with 329210 additions and 26644 deletions
+1
View File
@@ -0,0 +1 @@
+542
View File
@@ -0,0 +1,542 @@
# coding: utf-8
import os, sys, time, json
panelPath = '/www/server/panel'
os.chdir(panelPath)
if not panelPath + "/class/" in sys.path:
sys.path.insert(0, panelPath + "/class/")
import public, re
class databaseBase:
def get_base_list(self, args, sql_type='mysql'):
"""
@获取数据库列表
@type:数据库类型,MySQL,SQLServer
"""
search = ''
if 'search' in args: search = args['search']
SQL = public.M('databases');
where = "lower(type) = lower('{}')".format(sql_type)
if search:
where += "AND (name like '%{search}%' or ps like '%{search}%')".format(search=search)
if 'db_type' in args:
where += " AND db_type='{}'".format(args['db_type'])
if 'sid' in args:
where += " AND sid='{}'".format(args['sid'])
order = "id desc"
if hasattr(args, 'order'): order = args.order
info = {}
rdata = {}
info['p'] = 1
info['row'] = 20
result = '1,2,3,4,5,8'
info['count'] = SQL.where(where, ()).count();
if hasattr(args, 'limit'): info['row'] = int(args.limit)
if hasattr(args, 'result'): result = args.result;
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
rdata['where'] = where;
# 获取分页数据
rdata['page'] = page.GetPage(info, result)
# 取出数据
rdata['data'] = SQL.where(where, ()).order(order).field(
'id,sid,pid,name,username,password,accept,ps,addtime,type,db_type,conn_config').limit(
str(page.SHIFT) + ',' + str(page.ROW)).select()
for sdata in rdata['data']:
sdata['backup_count'] = public.M('backup').where("pid=? AND type=1", (sdata['id'])).count()
sdata['conn_config'] = json.loads(sdata['conn_config'])
return rdata;
def get_databaseModel(self):
'''
获取数据库模型对象
@db_type 数据库类型
'''
# from panelDatabaseController import DatabaseController
from panelDatabaseControllerV2 import DatabaseController
project_obj = DatabaseController()
return project_obj
def get_average_num(self, slist):
"""
@批量删除获取平均值
"""
count = len(slist)
limit_size = 1 * 1024 * 1024
if count <= 0: return limit_size
if len(slist) > 1:
slist = sorted(slist)
limit_size = int((slist[0] + slist[-1]) / 2 * 0.85)
return limit_size
def get_database_size(self, ids, is_pid=False):
"""
获取数据库大小
"""
result = {}
p = self.get_databaseModel()
for id in ids:
if not is_pid:
x = public.M('databases').where('id=?', id).field('id,sid,pid,name,type,ps,addtime').find()
else:
x = public.M('databases').where('pid=?', id).field('id,sid,pid,name,type,ps,addtime').find()
if not x: continue
x['backup_count'] = public.M('backup').where("pid=? AND type=?", (x['id'], '1')).count()
if x['type'] == 'MySQL':
x['total'] = int(public.get_database_size_by_id(id))
else:
try:
get = public.dict_obj()
get['data'] = {'db_id': x['id']}
get['mod_name'] = x['type'].lower()
get['def_name'] = 'get_database_size_by_id'
x['total'] = p.model(get)
except:
x['total'] = 0
result[x['name']] = x
return result
def check_base_del_data(self, get):
"""
@删除数据库前置检测
"""
ids = json.loads(get.ids)
slist = {};
result = [];
db_list_size = []
db_data = self.get_database_size(ids)
for key in db_data:
data = db_data[key]
if not data['id'] in ids: continue
db_addtime = public.to_date(times=data['addtime'])
data['score'] = int(time.time() - db_addtime) + data['total']
data['st_time'] = db_addtime
if data['total'] > 0: db_list_size.append(data['total'])
result.append(data)
slist['data'] = sorted(result, key=lambda x: x['score'], reverse=True)
slist['db_size'] = self.get_average_num(db_list_size)
return slist
def get_test(self, args):
p = self.get_databaseModel()
get = public.dict_obj()
get['data'] = {'db_id': 18}
get['mod_name'] = args['type'].lower()
get['def_name'] = 'get_database_size_by_id'
return p.model(get)
def add_base_database(self, get):
"""
@添加数据库前置检测
@return username 用户名
data_name 数据库名
data_pwd:数据库密码
"""
data_name = get['name'].strip().lower()
if self.check_recyclebin(data_name):
return public.returnMsg(False,
'Database [' + data_name + '] is already in recycle bin, please restore from recycle bin!');
if len(data_name) > 16:
return public.returnMsg(False, 'DATABASE_NAME_LEN')
if not hasattr(get, 'db_user'): get.db_user = data_name;
username = get.db_user.strip();
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
if username in checks or len(username) < 1:
return public.returnMsg(False, 'Database username is invalid!');
if data_name in checks or len(data_name) < 1:
return public.returnMsg(False, 'Database name is invalid!');
reg = r"^\w+$"
if not re.match(reg, data_name):
return public.returnMsg(False, 'DATABASE_NAME_ERR_T')
data_pwd = get['password']
if len(data_pwd) < 1:
data_pwd = public.md5(str(time.time()))[0:8]
if public.M('databases').where("name=? or username=?", (data_name, username)).count():
return public.returnMsg(False, 'DATABASE_NAME_EXISTS')
res = {
'data_name': data_name,
'username': username,
'data_pwd': data_pwd,
'status': True
}
return res
def delete_base_backup(self, get):
"""
@删除备份文件
"""
name = ''
id = get.id
where = "id=?"
filename = public.M('backup').where(where, (id,)).getField('filename')
if os.path.exists(filename): os.remove(filename)
if filename == 'qiniu':
name = public.M('backup').where(where, (id,)).getField('name');
public.ExecShell(public.get_run_python("[PYTHON] " + public.GetConfigValue(
'setup_path') + '/panel/script/backup_qiniu.py delete_file ' + name))
public.M('backup').where(where, (id,)).delete()
public.WriteLog("TYPE_DATABASE", 'DATABASE_BACKUP_DEL_SUCCESS', (name, filename))
public.return_message(0, 0, 'DEL_SUCCESS')
# 检查是否在回收站
def check_recyclebin(self, name):
try:
for n in os.listdir('{}/Recycle_bin'.format(public.get_soft_path())):
if n.find('BTDB_' + name + '_t_') != -1: return True;
return False;
except:
return False;
# map to list
def map_to_list(self, map_obj):
try:
if type(map_obj) != list and type(map_obj) != str: map_obj = list(map_obj)
return map_obj
except:
return []
# ******************************************** 远程数据库 ******************************************/
def check_cloud_args(self, get, nlist=[]):
"""
验证参数是否合法
@get param
@args 参数列表
"""
for key in nlist:
if not key in get:
return public.return_message(-1, 0, 'Parameter passing error, missing parameter {}!'.format(key))
# return public.returnMsg(False, 'Parameter passing error, missing parameter {}!'.format(key))
return True
def check_cloud_database(self, args):
'''
@检查远程数据库是否存在
@conn_config param
'''
p = self.get_databaseModel()
get = public.dict_obj()
# get['db_name'] = 'localhost'
get['data'] = args
get['mod_name'] = args['type']
get['def_name'] = 'check_cloud_database_status'
# public.print_log("-------------------进入检测远程数据库是否存在: {}".format(p.model(get)))
return p.model(get)
def AddBaseCloudServer(self, get):
"""
@name 添加远程服务器
@author hwliang<2021-01-10>
@param db_host<string> 服务器地址
@param db_port<port> 数据库端口
@param db_user<string> 用户名
@param db_password<string> 数据库密码
@param db_ps<string> 数据库备注
@param type<string> 数据库类型,mysql/sqlserver/sqlite
@return dict
"""
# mongodb {"db_host":"192.168.168.12","db_port":"27017","db_user":"root","db_password":"8thA5dgB8lr5ACfx","db_ps":"cecee","type":"mongodb"}
# sqlserver {"db_host":"192.168.1.23","db_port":"1433","db_user":"sa","db_password":"MfyDytnjXBTD8e6x","db_ps":"666","type":"sqlserver"}
arrs = ['db_host', 'db_port', 'db_user', 'db_password', 'db_ps', 'type']
if get.type == 'redis':
arrs = ['db_host', 'db_port', 'db_password', 'db_ps', 'type']
# try:
cRet = self.check_cloud_args(get, arrs)
if isinstance(cRet, dict):
return cRet
# try:
get['db_name'] = None
try:
res = self.check_cloud_database(get)
except BaseException as ex:
# public.print_log("获取远程数据库状态00: {}".format(ex))
return public.return_message(-1, 0, 'Database connection failed')
# # mongodb 远程检测有问题 暂时跳过检测
# if get.type != 'mongodb':
# if res['message'].get('result', '') == '' or res['message'].get('result', '') == False:
# return public.return_message(-1, 0, "The remote database could not be connected")
# {'status': 0, 'timestamp': 1715394490, 'message': AttributeError("'str' object has no attribute 'command'")}
# 检测数据库连接状态
try:
if not isinstance(res['message'], dict):
return public.return_message(-1, 0, "The remote database could not be connected")
if res['message'].get('result', '') == '' or res['message'].get('result', '') == False:
return public.return_message(-1, 0, "The remote database could not be connected")
if res['status'] == -1:
return public.return_message(-1, 0, "The remote database could not be connected")
except Exception as e:
# public.print_log("获取远程数据库状态22: {}".format(e))
return public.return_message(-1, 0, "The remote database could not be connected")
if public.M('database_servers').where('db_host=? AND db_port=?', (get['db_host'], get['db_port'])).count():
return public.return_message(-1, 0, 'The specified server already exists: [{}:{}]'.format(get['db_host'],
get['db_port']))
get['db_port'] = int(get['db_port'])
pdata = {
'db_host': get['db_host'],
'db_port': int(get['db_port']),
'db_user': get['db_user'],
'db_password': get['db_password'],
'db_type': get['type'],
'ps': public.xssencode2(get['db_ps'].strip()),
'addtime': int(time.time())
}
result = public.M("database_servers").insert(pdata)
if isinstance(result, int):
public.WriteLog('Database manager', 'Add remote MySQL server[{}:{}]'.format(get['db_host'], get['db_port']))
# return public.returnMsg(True,'Added successfully!')
return public.return_message(0, 0, 'Added successfully!')
# return public.returnMsg(False,'Add failed {}'.format(result))
return public.return_message(0, 0, 'Add failed {}'.format(result))
# except Exception as ex:
# public.print_log("error info777: {}".format(ex))
# return public.return_message(-1, 0, str(ex))
def GetBaseCloudServer(self, get):
'''
@name 获取远程服务器列表
@author hwliang<2021-01-10>
@return list
'''
where = '1=1'
if 'type' in get: where = "db_type = '{}'".format(get['type'])
data = public.M('database_servers').where(where, ()).select()
if not isinstance(data, list): data = []
if get['type'] == 'mysql':
bt_mysql_bin = public.get_mysql_info()['path'] + '/bin/mysql.exe'
if os.path.exists(bt_mysql_bin):
data.insert(0, {'id': 0, 'db_host': '127.0.0.1', 'db_port': 3306, 'db_user': 'root', 'db_password': '',
'ps': 'local server', 'addtime': 0, 'db_type': 'mysql'})
elif get['type'] == 'sqlserver':
pass
elif get['type'] == 'mongodb':
if os.path.exists('/www/server/mongodb/bin'):
data.insert(0, {'id': 0, 'db_host': '127.0.0.1', 'db_port': 27017, 'db_user': 'root', 'db_password': '',
'ps': 'local server', 'addtime': 0, 'db_type': 'mongodb'})
elif get['type'] == 'redis':
if os.path.exists('/www/server/redis'):
data.insert(0, {'id': 0, 'db_host': '127.0.0.1', 'db_port': 6379, 'db_user': 'root', 'db_password': '',
'ps': 'local server', 'addtime': 0, 'db_type': 'redis'})
elif get['type'] == 'pgsql':
if os.path.exists('/www/server/pgsql'):
data.insert(0,
{'id': 0, 'db_host': '127.0.0.1', 'db_port': 5432, 'db_user': 'postgres', 'db_password': '',
'ps': 'local server', 'addtime': 0, 'db_type': 'pgsql'})
return data
def RemoveBaseCloudServer(self, get):
'''
@name 删除远程服务器
@author hwliang<2021-01-10>
@param id<int> 远程服务器ID
@return dict
'''
id = int(get.id)
if not id:
return public.return_message(-1, 0, 'Parameter passed error, please try again!')
db_find = public.M('database_servers').where('id=?', (id,)).find()
if not db_find:
return public.return_message(-1, 0, 'The specified remote server does not exist!')
public.M('databases').where('sid=?', id).delete()
result = public.M('database_servers').where('id=?', id).delete()
if isinstance(result, int):
public.WriteLog('Database manager',
'Delete remote MySQL server [{}:{}]'.format(db_find['db_host'], int(db_find['db_port'])))
return public.return_message(0, 0, 'Successfully deleted!')
return public.return_message(0, 0, 'Successfully deleted {}'.format(result))
def ModifyBaseCloudServer(self, get):
'''
@name 修改远程服务器
@author hwliang<2021-01-10>
@param id<int> 远程服务器ID
@param db_host<string> 服务器地址
@param db_port<port> 数据库端口
@param db_user<string> 用户名
@param db_password<string> 数据库密码
@param db_ps<string> 数据库备注
@return dict
'''
arrs = ['db_host', 'db_port', 'db_user', 'db_password', 'db_ps', 'type']
if get.type == 'redis':
arrs = ['db_host', 'db_port', 'db_password', 'db_ps', 'type']
cRet = self.check_cloud_args(get, arrs)
if isinstance(cRet, dict):
return cRet
# if not cRet['status']:
# return public.return_message(-1, 0,)
# return cRet
get['db_name'] = None
id = int(get.id)
get['db_port'] = int(get['db_port'])
db_find = public.M('database_servers').where('id=?', (id,)).find()
if not db_find:
return public.return_message(-1, 0, 'The specified remote server does not exist!')
_modify = False
if db_find['db_host'] != get['db_host'] or db_find['db_port'] != get['db_port']:
_modify = True
if public.M('database_servers').where('db_host=? AND db_port=?', (get['db_host'], get['db_port'])).count():
return public.return_message(-1, 0,
'The specified server already exists: [{}:{}]'.format(get['db_host'],
get['db_port']))
if db_find['db_user'] != get['db_user'] or db_find['db_password'] != get['db_password']:
_modify = True
_modify = True
if _modify:
try:
res = self.check_cloud_database(get)
except BaseException as ex:
# public.print_log("获取远程数据库链接状态报错: {}".format(ex))
return public.return_message(-1, 0, 'Database connection failed')
if res['message'].get('result', '') == '' or res['message'].get('result', '') == False:
return public.return_message(-1, 0, "The remote database could not be connected")
pdata = {
'db_host': get['db_host'],
'db_port': int(get['db_port']),
'db_user': get['db_user'],
'db_password': get['db_password'],
'db_type': get['type'],
'ps': public.xssencode2(get['db_ps'].strip())
}
result = public.M("database_servers").where('id=?', (id,)).update(pdata)
if isinstance(result, int):
public.WriteLog('Database manager',
'Modify the remote MySQL server[{}:{}]'.format(get['db_host'], get['db_port']))
return public.return_message(0, 0, 'Successfully modified!')
return public.return_message(-1, 0, 'Fail to edit {}'.format(result))
# 检测数据库执行错误
def IsSqlError(self, mysqlMsg):
if mysqlMsg:
mysqlMsg = str(mysqlMsg)
if "MySQLdb" in mysqlMsg:
return public.return_message(-1, 0, 'DATABASE_ERR_MYSQLDB')
if "2002," in mysqlMsg:
return public.return_message(-1, 0, 'DATABASE_ERR_CONNECT')
if "2003," in mysqlMsg:
return public.return_message(-1, 0,
'Database connection timed out, please check if the configuration is correct.')
if "1045," in mysqlMsg:
return public.return_message(-1, 0, 'MySQL password error.')
if "1040," in mysqlMsg:
return public.return_message(-1, 0,
'Exceeded maximum number of connections, please try again later.')
if "1130," in mysqlMsg:
return public.return_message(-1, 0,
'Database connection failed, please check whether the root user is authorized to access 127.0.0.1.')
if "using password:" in mysqlMsg:
return public.return_message(-1, 0, 'DATABASE_ERR_PASS')
if "Connection refused" in mysqlMsg:
return public.return_message(-1, 0, 'DATABASE_ERR_CONNECT')
if "1133" in mysqlMsg:
return public.return_message(-1, 0, 'DATABASE_ERR_NOT_EXISTS')
if "2005_login_error" == mysqlMsg:
return public.return_message(-1, 0,
'The connection times out, please manually enable the TCP/IP function (Start Menu->SQL 2005->Configuration Tools->2005 Network Configuration->TCP/IP->Enable)')
if 'already exists' in mysqlMsg:
return public.return_message(-1, 0,
'The specified database already exists, please do not add it repeatedly.')
if 'Cannot open backup device' in mysqlMsg:
return public.return_message(-1, 0,
'The operation failed, the remote database does not support the operation.')
if '1142' in mysqlMsg:
return public.return_message(-1, 0, 'Insufficient permissions, please use root user.')
if "DB-Lib error message 20018" in mysqlMsg:
return public.return_message(-1, 0,
'Create failed, SQL Server requires GUI support')
return None
# ******************************************** 数据库公用方法 ******************************************/
if __name__ == "__main__":
# get = {}
# get['db_host'] = '192.168.1.37'
# get['db_port'] = '3306'
# get['db_user'] = 'root'
# get['db_password'] = 'HLANEMJFRbPE7Ny2'
# get['db_ps'] = '2'
# get['type'] = 'mysql'
# bt = databaseBase()
# ret = bt.AddCloudServer(get)
# print(ret)
get = {}
get['db_host'] = '192.168.66.73'
get['db_port'] = '1433'
get['db_user'] = 'sa'
get['db_password'] = 'dPYi6Gt8GC7SL58C'
get['db_ps'] = '2'
get['type'] = 'sqlserver'
bt = databaseBase()
ret = bt.get_test(get)
print(ret)
+933
View File
@@ -0,0 +1,933 @@
#coding: utf-8
#-------------------------------------------------------------------
# aaPanel
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
#-------------------------------------------------------------------
# Author: hwliang <hwl@aapanel.com>
#-------------------------------------------------------------------
#角色说明:
#read:允许用户读取指定数据库
#readWrite:允许用户读写指定数据库
#dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
#userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
#clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
#readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
#readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
#userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
#dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
#root:只在admin数据库中可用。超级账号,超级权限
# sqlite模型
#------------------------------
import os,re,json,time
from databaseModelV2.base import databaseBase
import public
from public.validate import Param
try:
import pymongo
except:
public.ExecShell("btpip install pymongo")
import pymongo
try:
from BTPanel import session
except :pass
class panelMongoDB():
__DB_PASS = None
__DB_USER = None
__DB_PORT = 27017
__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 __Conn(self,auth):
if not self.__DB_CLOUD:
path = '{}/data/mongo.root'.format(public.get_panel_path())
if os.path.exists(path): self.__DB_PASS = public.readFile(path)
self.__DB_PORT = int(self.__config['port'])
try:
if not self.__DB_USER and auth:
self.__DB_USER = "root"
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=self.__DB_PORT, username = self.__DB_USER, password=self.__DB_PASS)
self.__DB_CONN.admin.command({"listDatabases":1})
return True
except :
try:
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=self.__DB_PORT, username = self.__DB_USER, password=self.__DB_PASS)
self.__DB_CONN.admin.authenticate('root', self.__DB_PASS)
return True
except :
self.__DB_ERR = public.get_error_info()
return False
def get_db_obj(self,db_name = 'admin',auth=0):
"""
@获取连接对象
"""
if not self.__Conn(auth): return self.__DB_ERR
return self.__DB_CONN[db_name]
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_config(self,get):
filename = '{}/mongodb/config.conf'.format(public.get_setup_path())
if os.path.exists(filename):
return public.readFile(filename)
return ""
#获取配置项
def get_options(self,get):
options = ['port','bind_ip','logpath','dbpath','authorization']
data = {}
conf = self.get_config(None)
for opt in options:
tmp = re.findall(opt + r":\s+(.+)",conf)
if not tmp: continue;
data[opt] = tmp[0]
if not 'authorization' in data:data['authorization'] = "disabled"
# public.writeFile('/www/server/1.txt',json.dumps(data))
return data
class main(databaseBase):
__conf_path = '{}/mongodb/config.conf'.format(public.get_setup_path())
def __init__(self):
pass
def get_list(self,args):
"""
@获取数据库列表
@sql_type = sqlserver
"""
# {"table": "databases", "search": "", "limit": 20, "p": 1}
# 校验参数
try:
args.validate([
Param('table').Require().String().Xss(),
Param('search').String(),
Param('order').String().Xss(),
Param('limit').Integer(),
Param('p').Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
# return self.get_base_list(args, sql_type = 'mongodb')
return public.return_message(0, 0, self.get_base_list(args, sql_type = 'mongodb'))
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)
# return public.return_message(0, 0, self.AddBaseCloudServer(args))
def RemoveCloudServer(self,args):
'''
@删除远程数据库
'''
return self.RemoveBaseCloudServer(args)
# return public.return_message(0, 0, self.RemoveBaseCloudServer(args))
def ModifyCloudServer(self,args):
'''
@修改远程数据库
'''
return self.ModifyBaseCloudServer(args)
# return public.return_message(0, 0, self.ModifyBaseCloudServer(args))
#获取数据库列表
def exists_databases(self,get):
db_name = get
if type(get) != str:db_name = get['db_name']
auth_status = self.get_local_auth(get)
db_obj = self.get_obj_by_sid(self.sid).get_db_obj('admin',auth=auth_status)
data = db_obj.command({"listDatabases":1})
if 'databases' in data:
for x in data['databases']:
if x['name'] == db_name:
return True
return False
def __set_auth_open(self,status):
"""
@设置数据库密码访问开关
@状态 status:1 开启,2:关闭
"""
conf = public.readFile(self.__conf_path)
if status:
conf = re.sub(r'authorization\s*\:\s*disabled','authorization: enabled',conf)
else:
conf = re.sub(r'authorization\s*\:\s*enabled','authorization: disabled',conf)
public.writeFile(self.__conf_path,conf)
self.restart_services()
return True
def set_auth_status(self,get):
"""
@设置密码认证状态
@status int 0:关闭,1:开启
"""
if not public.process_exists("mongod"):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
status = int(get.status)
path = '{}/data/mongo.root'.format(public.get_panel_path())
if status:
if hasattr(get,'password'):
password = get['password'].strip()
if not password or not re.search(r"^[\w@\.]+$", password):
# return public.return_msg_gettext(False, 'Database password cannot be empty or have special characters!')
return public.return_message(-1, 0, 'Database password cannot be empty or have special characters!')
# if re.search('[\u4e00-\u9fa5]',password):
# return public.returnMsg(False,'Database password cannot be Chinese, please change the name!')
else:
password = public.GetRandomString(16)
self.__set_auth_open(0)
_client = panelMongoDB().get_db_obj('admin')
try:
_client.command("dropUser", "root")
except : pass
_client.command("createUser", "root", pwd=password, roles=[
{'role':'root','db':'admin'},
{'role':'clusterAdmin','db':'admin'},
{'role':'readAnyDatabase','db':'admin'},
{'role':'readWriteAnyDatabase','db':'admin'},
{'role':'userAdminAnyDatabase','db':'admin'},
{'role':'dbAdminAnyDatabase','db':'admin'},
{'role':'userAdmin','db':'admin'},
{'role':'dbAdmin','db':'admin'}
])
self.__set_auth_open(1)
public.writeFile(path,password)
else:
if os.path.exists(path): os.remove(path)
self.__set_auth_open(0)
# return public.return_msg_gettext(True,'Setup successfully!')
return public.return_message(0, 0, 'Setup successfully!')
def restart_services(self):
"""
@重启服务
"""
public.ExecShell('/etc/init.d/mongodb restart')
return True
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 = panelMongoDB()
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 = panelMongoDB()
return db_obj
def get_local_auth(self,get):
"""
@验证本地数据库是否需要密码
"""
self.sid = get.get('sid/d',0)
if self.sid != 0: return True
conf = panelMongoDB().get_options(None)
if conf['authorization'] == 'enabled':
return True
return False
def AddDatabase(self,args):
"""
@添加数据库
"""
# 校验参数
try:
args.validate([
Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
# try:
# int(args.sid)
# except:
# return public.returnMsg(False, 'Database type sid needs int type!')
if not int(args.sid) and not public.process_exists("mongod"):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
# try:
username = ''
password = ''
auth_status = self.get_local_auth(args) #auth为true时如果__DB_USER为空则将它赋值为 root,用于开启本地认证后数据库用户为空的情况
data_name = args.name.strip()
# 检测重复添加
find = public.M('databases').where("name=?", (data_name,)).find()
if find:
return public.return_message(-1, 0, 'Cannot be added repeatedly')
if not data_name:
# return public.returnMsg(False, "Database name cannot be empty!")
return public.return_message(-1, 0, "Database name cannot be empty!")
if auth_status:
res = self.add_base_database(args)
if not res['status']:
# return res
return public.return_message(-1, 0, res['msg'])
data_name = res['data_name']
username = res['username']
password = res['data_pwd']
else:
username = data_name
db_obj = self.get_obj_by_sid(self.sid).get_db_obj(data_name,auth=auth_status)
dtype = 'MongoDB'
if not hasattr(args,'ps'): args['ps'] = public.getMsg('INPUT_PS');
addTime = time.strftime('%Y-%m-%d %X',time.localtime())
pid = 0
if hasattr(args,'pid'): pid = args.pid
if hasattr(args,'contact'):
site = public.M('sites').where("id=?",(args.contact,)).field('id,name').find()
if site:
pid = int(args.contact)
args['ps'] = site['name']
db_type = 0
if self.sid: db_type = 2
db_obj.chat.insert_one({})
if auth_status:
db_obj.command("createUser", username, pwd=password, roles=[{'role':'dbOwner','db':data_name},{'role':'userAdmin','db':data_name}])
public.set_module_logs('linux_mongodb','AddDatabase',1)
#添加入SQLITE
public.M('databases').add('pid,sid,db_type,name,username,password,accept,ps,addtime,type',(pid,self.sid,db_type,data_name,username,password,'127.0.0.1',args['ps'],addTime,dtype))
public.WriteLog("TYPE_DATABASE", 'DATABASE_ADD_SUCCESS',(data_name,))
# return public.returnMsg(True,'ADD_SUCCESS')
return public.return_message(0, 0, 'ADD_SUCCESS')
# except Exception as ex:
# public.print_log("error info66: {}".format(ex))
# return public.return_message(-1, 0, str(ex))
def DeleteDatabase(self,args):
"""
@删除数据库
"""
# 校验参数
try:
args.validate([
Param('id').Require().Integer(),
Param('name').Require().String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
id = args['id']
find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid,db_type').find()
if not find:
# return public.returnMsg(False,'The specified database does not exist.')
return public.return_message(-1, 0, 'The specified database does not exist.')
# try:
# int(find['sid'])
# except:
# return public.returnMsg(False, 'Database type sid needs int type!')
if not public.process_exists("mongod") and not int(find['sid']):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
name = args['name']
username = find['username']
auth_status = self.get_local_auth(args)
db_obj = self.get_obj_by_sid(find['sid']).get_db_obj(name,auth_status)
try:
db_obj.command("dropUser", username)
except :
pass
db_obj.command('dropDatabase')
#删除SQLITE
public.M('databases').where("id=?",(id,)).delete()
public.WriteLog("Database manager", 'Successfully deleted!',(name,))
# return public.returnMsg(True, 'Successfully deleted!')
return public.return_message(0, 0, 'Successfully deleted!')
def get_info_by_db_id(self,db_id):
"""
@获取数据库连接详情
@db_id 数据库id
"""
find = public.M('databases').where("id=?" ,db_id).find()
if not find: return False
data = {
'db_host':'127.0.0.1',
'db_port':int(panelMongoDB().get_options(None)['port']),
'db_user':find['username'],
'db_password':find['password']
}
if int(find['sid']):
conn_config = public.M('database_servers').where("id=?" ,find['sid']).find()
data['db_host'] = conn_config['db_host']
data['db_port'] = int(conn_config['db_port'])
return data
#导入
def InputSql(self,args):
# 校验参数
try:
args.validate([
Param('file').SafePath(), # 文件路径
Param('name').String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
name = args.name
file = args.file
# try:
if not os.path.exists(file):
# return public.returnMsg(False,'The import path does not exist!')
return public.return_message(-1, 0, 'The import path does not exist!')
if not os.path.isfile(file):
# return public.returnMsg(False,'Only importing compressed files is supported!')
return public.return_message(-1, 0, 'Only importing compressed files is supported!')
find = public.M('databases').where("name=? AND LOWER(type)=LOWER('MongoDB')",(name,)).find()
if not find:
# return public.returnMsg(False,'This database was not found!')
return public.return_message(-1, 0, 'This database was not found!')
get = public.dict_obj()
get.sid = find['sid']
if not public.process_exists("mongod") and not int(find['sid']):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
info = self.get_info_by_db_id(find['id'])
mongorestore_obj = '{}/mongodb/bin/mongorestore'.format(public.get_setup_path())
mongoimport_obj = '{}/mongodb/bin/mongoimport'.format(public.get_setup_path())
if not os.path.exists(mongorestore_obj):
# return public.returnMsg(False,'Lack of backup tools, please install MongoDB through [APP Store] first!')
return public.return_message(-1, 0, 'Lack of backup tools, please install MongoDB through [APP Store] first!')
dir_tmp, file_tmp = os.path.split(file)
split_tmp = file_tmp.split(".")
ext = split_tmp[-1]
ext_err = ".".join(split_tmp[1:])
if len(split_tmp[1:]) == 2 and split_tmp[1] not in ['json', 'csv']:
# return public.returnMsg(False, f'.{ext_err} This file format is not currently supported')
return public.return_message(-1, 0, f'.{ext_err} This file format is not currently supported')
if ext not in ['json', 'csv', 'gz', 'zip']:
# return public.returnMsg(False, f'.{ext_err} This file format is not currently supported')
return public.return_message(-1, 0, f'.{ext_err} This file format is not currently supported')
tmpFile = ".".join(split_tmp[:-1])
isgzip = False
if ext != '': # gz zip
if tmpFile == '':
# return public.returnMsg(False, 'FILE_NOT_EXISTS', (tmpFile,))
return public.return_message(-1, 0, 'FILE_NOT_EXISTS', (tmpFile,))
isgzip = True
# 面板默认备份路径
backupPath = session['config']['backup_path'] + '/database'
input_path = os.path.join(backupPath, tmpFile)
# 备份文件的路径
input_path2 = os.path.join(dir_tmp, tmpFile)
if ext == 'zip': # zip
public.ExecShell("cd " + backupPath + " && unzip " + '"' + file + '"')
else: # gz
public.ExecShell("cd " + backupPath + " && tar zxf " + '"' + file + '"')
if not os.path.exists(input_path):
# 兼容从备份文件所在目录恢复
if not os.path.exists(input_path2):
public.ExecShell("cd " + backupPath + " && gunzip -q " + '"' + file + '"')
else:
input_path = input_path2
if not os.path.exists(input_path) and os.path.isfile(input_path2):
input_path = input_path2
else:
input_path = file
if os.path.isdir(input_path): # zip,gz,bson
if self.get_local_auth(get):
for temp_file in os.listdir(input_path):
shell = f"""
{mongorestore_obj} \
--host={info['db_host']} \
--port={info['db_port']} \
--db={find['name']} \
--username={info['db_user']} \
--password={info['db_password']} \
--drop \
{os.path.join(input_path, temp_file)}
"""
public.ExecShell(shell)
else:
for temp_file in os.listdir(input_path):
shell = f"""
{mongorestore_obj} \
--host={info['db_host']} \
--port={info['db_port']} \
--db={find['name']} \
--drop \
{os.path.join(input_path, temp_file)}
"""
public.ExecShell(shell)
if isgzip is True:
public.ExecShell("rm -f " + input_path)
else:# json,csv
file_tmp = os.path.basename(input_path)
file_name = file_tmp.split(".")[0]
ext = file_tmp.split(".")[-1]
if ext not in ["json","csv"]:
# return public.returnMsg(False, 'File format is incorrect!')
return public.return_message(-1, 0, 'File format is incorrect!')
shell_txt = ""
if ext == "csv":
fp = open(input_path, "r")
fields_list = fp.readline()
fp.close()
shell_txt = f"--fields={fields_list}"
if self.get_local_auth(get):
shell = f"""
{mongoimport_obj} \
--host={info['db_host']} \
--port={info['db_port']} \
--db={find['name']} \
--username={info['db_user']} \
--password={info['db_password']} \
--collection={file_name} \
--file={input_path} \
--type={ext} \
--drop
"""
else:
shell = f"""
{mongoimport_obj} \
--host={info['db_host']} \
--port={info['db_port']} \
--db={find['name']} \
--collection={file_name} \
--file={input_path} \
--type={ext} \
--drop
"""
shell = f"{shell} {shell_txt}"
public.ExecShell(shell)
public.WriteLog("Database manager", 'Import database [{}] succeeded'.format(name))
# return public.returnMsg(True, 'Successfully imported database!')
return public.return_message(0, 0, 'Successfully imported database!')
# except Exception as ex:
# public.print_log("error info66: {}".format(ex))
# return public.return_message(-1, 0, str(ex))
#######################
def ToBackup(self,args):
"""
@备份数据库 id 数据库id
"""
# 校验参数
try:
args.validate([
Param('id').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
id = args['id']
find = public.M('databases').where("id=? AND LOWER(type)=LOWER('MongoDB')",(id,)).find()
if not find:
# return public.returnMsg(False,'The specified database does not exist.')
return public.return_message(-1, 0, 'The specified database does not exist.')
fileName = f"{find['name']}_mongodb_data_{time.strftime('%Y%m%d_%H%M%S',time.localtime())}"
backupName = session['config']['backup_path'] + '/database/mongodb/' + fileName
spath = os.path.dirname(backupName)
if not os.path.exists(spath): os.makedirs(spath)
get = public.dict_obj()
get.sid = find['sid']
try:
sid = int(find['sid'])
except:
# return public.returnMsg(False, 'Database type sid needs int type!')
return public.return_message(-1, 0, 'Database type sid needs int type!')
if not public.process_exists("mongod") and not int(find['sid']):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
info = self.get_info_by_db_id(id)
sql_dump = '{}/mongodb/bin/mongodump'.format(public.get_setup_path())
if not os.path.exists(sql_dump):
# return public.returnMsg(False,'Lack of backup tools, please install MongoDB through [APP Store] first!')
return public.return_message(-1, 0, 'Lack of backup tools, please install MongoDB through [APP Store] first!')
if self.get_local_auth(get):
if not info['db_password']:
# return public.returnMsg(False,'Password authentication has been enabled. The password cannot be empty when the database is backed up. Please set a password and try again!')
return public.return_message(-1, 0, 'Password authentication has been enabled. The password cannot be empty when the database is backed up. Please set a password and try again!')
shell = "{} -h {} --port {} -u {} -p {} -d {} -o {} ".format(sql_dump,info['db_host'],info['db_port'],info['db_user'],info['db_password'],find['name'] ,backupName)
else:
shell = "{} -h {} --port {} -d {} -o {} ".format(sql_dump,info['db_host'],info['db_port'],find['name'] ,backupName)
ret = public.ExecShell(shell)
if not os.path.exists(backupName):
# return public.returnMsg(False,'Database backup failed, file does not exist');
return public.return_message(-1, 0, 'Database backup failed, file does not exist');
backupFile = f"{backupName}.zip"
public.ExecShell(f"cd {spath} && zip {backupFile} -r {fileName}")
fileName = f"{fileName}.zip"
public.M('backup').add('type,name,pid,filename,size,addtime',(1,fileName,id,backupFile,0,time.strftime('%Y-%m-%d %X',time.localtime())))
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS",(find['name'],))
public.ExecShell(f"rm -rf {backupName}")
if not os.path.exists(backupFile):
# return public.returnMsg(True, 'Backup failed,{}.'.format(ret[0]))
return public.return_message(0, 0, 'Backup failed,{}.'.format(ret[0]))
if os.path.getsize(backupFile) < 1:
# return public.returnMsg(True, 'The backup is executed successfully, the backup file is less than 1b, please check the backup integrity.')
return public.return_message(0, 0, 'The backup is executed successfully, the backup file is less than 1b, please check the backup integrity.')
else:
# return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_message(0, 0, 'BACKUP_SUCCESS')
def DelBackup(self,args):
"""
@删除备份文件
"""
return self.delete_base_backup(args)
# return public.return_message(0, 0, self.delete_base_backup(args))
#同步数据库到服务器
def SyncToDatabases(self,get):
type = int(get['type'])
n = 0
sql = public.M('databases')
if type == 0:
data = sql.field('id,name,username,password,accept,type,sid,db_type').where('type=?',('MongoDB',)).select()
for value in data:
if value['db_type'] in ['1',1]:
continue # 跳过远程数据库
result = self.ToDataBase(value)
if result == 1: n +=1
else:
import json
data = json.loads(get.ids)
for value in data:
find = sql.where("id=?",(value,)).field('id,name,username,password,sid,db_type,accept,type').find()
result = self.ToDataBase(find)
if result == 1: n +=1
if n == 1:
# return public.returnMsg(True, 'Synchronization succeeded')
return public.return_message(0, 0, 'Synchronization succeeded')
elif n == 0:
# return public.returnMsg(False,'Sync failed')
return public.return_message(-1, 0, 'No synchronized database')
# return public.returnMsg(True,'DATABASE_SYNC_SUCCESS',(str(n),))
return public.return_message(0, 0, 'DATABASE_SYNC_SUCCESS {}'.format(n))
#添加到服务器
def ToDataBase(self,find):
if find['username'] == 'bt_default':
# return 0
return public.return_message(0, 0, 0)
if len(find['password']) < 3 :
find['username'] = find['name']
find['password'] = public.md5(str(time.time()) + find['name'])[0:10]
public.M('databases').where("id=?",(find['id'],)).save('password,username',(find['password'],find['username']))
self.sid = find['sid']
try:
int(find['sid'])
except:
return public.return_message(-1, 0, 'Database type sid needs int type!')
# return public.returnMsg(False, 'Database type sid needs int type!')
if not public.process_exists("mongod") and not int(find['sid']):
# return public.returnMsg(False,"Mongodb service has not been started yet!")
return public.return_message(-1, 0, "Mongodb service has not been started yet!")
get = public.dict_obj()
get.sid = self.sid
auth_status = self.get_local_auth(get)
if auth_status:
db_obj = self.get_obj_by_sid(self.sid).get_db_obj(find['name'], auth_status)
try:
db_obj.chat.insert_one({})
db_obj.command("dropUser", find['username'])
except :pass
try:
db_obj.command("createUser", find['username'], pwd=find['password'], roles=[{'role':'dbOwner','db':find['name']},{'role':'userAdmin','db':find['name']}])
except:
pass
# return 1
return public.return_message(0, 0, 1)
def SyncGetDatabases(self,get):
"""
@从服务器获取数据库
"""
n = 0;s = 0;
db_type = 0
self.sid = get.get('sid/d',0)
if self.sid: db_type = 2
try:
int(get.sid)
except:
# return public.returnMsg(False, 'The database type SID requires an INT!')
return public.return_message(-1, 0, 'The database type SID requires an INT!')
if not public.process_exists("mongod") and not int(get.sid):
# return public.returnMsg(False,"The Mongodb service is not enabled!")
return public.return_message(-1, 0, "The Mongodb service is not enabled!")
auth_status = self.get_local_auth(get)
data = self.get_obj_by_sid(self.sid).get_db_obj('admin',auth=auth_status).command({"listDatabases":1})
sql = public.M('databases')
nameArr = ['information_schema','performance_schema','mysql','sys','master','model','msdb','tempdb','config','local','admin']
for item in data['databases']:
dbname = item['name']
if sql.where("name=?",(dbname,)).count(): continue
if not dbname in nameArr:
if sql.table('databases').add('name,username,password,accept,ps,addtime,type,sid,db_type',(dbname,dbname,'','',public.getMsg('INPUT_PS'),time.strftime('%Y-%m-%d %X',time.localtime()),'MongoDB',self.sid,db_type)): n +=1
# return public.returnMsg(True,'DATABASE_GET_SUCCESS',(str(n),))
return public.return_message(0, 0, 'DATABASE_GET_SUCCESS {}'.format(n))
def ResDatabasePassword(self,args):
"""
@修改用户密码
"""
id = args['id']
username = args['name'].strip()
newpassword = public.trim(args['password'])
try:
if not newpassword:
# return public.returnMsg(False, 'Modify the failureThe database[' + username + ']password cannot be empty.');
return public.return_message(-1, 0, 'Modify the failureThe database[' + username + ']password cannot be empty.');
if len(re.search(r"^[\w@\.]+$", newpassword).groups()) > 0:
# return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
return public.return_message(-1, 0, 'The database password cannot be empty or contain special characters')
if re.search('[\u4e00-\u9fa5]',newpassword):
# return public.returnMsg(False,'Database password cannot be Chinese, please change the name!')
return public.return_message(-1, 0, 'Database password cannot be Chinese, please change the name!')
except :
# return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
return public.return_message(-1, 0, 'The database password cannot be empty or contain special characters')
find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid').find();
if not find:
# return public.returnMsg(False, 'The modification failed because the specified database does not exist.');
return public.return_message(-1, 0, 'The modification failed because the specified database does not exist.');
get = public.dict_obj()
get.sid = find['sid']
try:
int(find['sid'])
except:
# return public.returnMsg(False, 'The database type SID requires an INT!')
return public.return_message(-1, 0, 'The database type SID requires an INT!')
if not public.process_exists("mongod") and not int(find['sid']):
# return public.returnMsg(False,"The Mongodb service is not enabled!")
return public.return_message(-1, 0, "The Mongodb service is not enabled!")
auth_status = self.get_local_auth(args)
if auth_status:
db_obj = self.get_obj_by_sid(find['sid']).get_db_obj(username,auth=auth_status)
try:
print(db_obj.command("updateUser", username, pwd = newpassword))
except :
print(db_obj.command("createUser", username, pwd=newpassword, roles=[{'role':'dbOwner','db':find['name']},{'role':'userAdmin','db':find['name']}]))
else:
# return public.returnMsg(False, 'Password access is not enabled for the database.')
return public.return_message(-1, 0, 'Password access is not enabled for the database.')
#修改SQLITE
public.M('databases').where("id=?",(id,)).setField('password',newpassword)
public.WriteLog("TYPE_DATABASE",'DATABASE_PASS_SUCCESS',(find['name'],))
# return public.returnMsg(True,'DATABASE_PASS_SUCCESS',(find['name'],))
return public.return_message(0, 0, 'DATABASE_PASS_SUCCESS',(find['name'],))
def get_root_pwd(self,args):
"""
@获取root密码
"""
config = panelMongoDB().get_options(None)
sa_path = '{}/data/mongo.root'.format(public.get_panel_path())
if os.path.exists(sa_path):
config['msg'] = public.readFile(sa_path)
else:
config['msg'] = ''
config['root'] = config['msg']
# return config
return public.return_message(0, 0, config)
def get_database_size_by_id(self, args):
"""
@获取数据库尺寸(批量删除验证)
@args json/int 数据库id
"""
# if not public.process_exists("mongod"):
# return public.returnMsg(False,"The Mongodb service is not enabled!")
total = 0
db_id = args
if not isinstance(args, int): db_id = args['db_id']
find = public.M('databases').where('id=?', db_id).find()
try:
int(find['sid'])
except:
# return 0
return public.return_message(0, 0, 0)
if not public.process_exists("mongod") and not int(find['sid']):
# return 0
return public.return_message(0, 0, 0)
try:
auth_status = self.get_local_auth(args)
db_obj = self.get_obj_by_sid(find['sid']).get_db_obj(find['name'], auth=auth_status)
print(db_obj)
print(db_obj.stats())
total = tables[0][1]
if not total: total = 0
except:
print(public.get_error_info())
# return total
return public.return_message(0, 0, total)
def check_del_data(self,args):
"""
@删除数据库前置检测
"""
# return self.check_base_del_data(args)
return public.return_message(0, 0, self.check_base_del_data(args))
def check_cloud_database_status(self,conn_config):
"""
@检测远程数据库是否连接
@conn_config 远程数据库配置,包含host port pwd等信息
"""
try:
if not 'db_name' in conn_config: conn_config['db_name'] = None
sql_obj = panelMongoDB().set_host(conn_config['db_host'],conn_config['db_port'],conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
db_obj = sql_obj.get_db_obj('admin')
data = db_obj.command({"listDatabases":1})
if 'databases' in data:
# return True
return public.return_message(0, 0, True)
# return False
return public.return_message(-1, 0, False)
except Exception as ex:
# return public.returnMsg(False,ex)
return public.return_message(0, 0, ex)
+769
View File
@@ -0,0 +1,769 @@
# coding: utf-8
# -------------------------------------------------------------------
# aaPanel
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
# -------------------------------------------------------------------
# Author: hezhihong <bt_ahong@aapanel.com>
# -------------------------------------------------------------------
# ------------------------------
# postgresql模型
# ------------------------------
import os, re, json, time
from databaseModelV2.base import databaseBase
import public
try:
from BTPanel import session
except:
pass
try:
import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
except:
pass
class panelPgsql:
__DB_PASS = None
__DB_USER = 'postgres'
__DB_PORT = 5432
__DB_HOST = 'localhost'
__DB_CONN = None
__DB_CUR = None
__DB_ERR = None
__DB_CLOUD = 0 # 远程数据库
def __init__(self):
self.__DB_CLOUD = 0
if self.__DB_USER == 'postgres' and self.__DB_HOST == 'localhost' and self.__DB_PASS == None:
tmp_args = public.dict_obj()
tmp_args.is_True = True
self.__DB_PASS = main().get_root_pwd(tmp_args)
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 check_psycopg(self):
"""
@name检测依赖是否正常
"""
try:
import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
except:
os.system('btpip install psycopg2-binary')
try:
import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
except:
return False
return True
# 连接MYSQL数据库
def __Conn(self):
self.check_psycopg()
try:
import psycopg2
except:
self.__DB_ERR = public.get_error_info()
return False
try:
if self.__DB_USER == 'postgres' and self.__DB_HOST == 'localhost':
if not self.__DB_PASS:
tmp_args = public.dict_obj()
try:
self.__DB_PASS == main().get_root_pwd(tmp_args)['msg']
except:
pass
self.__DB_CONN = psycopg2.connect(user=self.__DB_USER, password=self.__DB_PASS, host=self.__DB_HOST,
port=self.__DB_PORT)
self.__DB_CONN.autocommit = True
self.__DB_CONN.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) # <-- ADD THIS LINE
self.__DB_CUR = self.__DB_CONN.cursor()
return True
except:
self.__DB_ERR = public.get_error_info()
print(self.__DB_ERR)
return False
def execute(self, sql):
# 执行SQL语句返回受影响行
if not self.__Conn(): return self.__DB_ERR
try:
# print(sql)
result = self.__DB_CUR.execute(sql)
self.__DB_CONN.commit()
self.__Close()
return result
except Exception as ex:
return ex
def query(self, sql):
# 执行SQL语句返回数据集
if not self.__Conn(): return self.__DB_ERR
try:
self.__DB_CUR.execute(sql)
result = self.__DB_CUR.fetchall()
data = list(map(list, result))
self.__Close()
return data
except Exception as ex:
return ex
# 关闭连接
def __Close(self):
self.__DB_CUR.close()
self.__DB_CONN.close()
class main(databaseBase, panelPgsql):
__ser_name = None
__soft_path = '/www/server/pgsql'
__setup_path = '/www/server/panel/'
__dbuser_info_path = "{}plugin/pgsql_manager_dbuser_info.json".format(__setup_path)
__plugin_path = "{}plugin/pgsql_manager/".format(__setup_path)
def __init__(self):
s_path = public.get_setup_path()
v_info = public.readFile("{}/pgsql/version.pl".format(s_path))
if v_info:
ver = v_info.split('.')[0]
self.__ser_name = 'postgresql-x64-{}'.format(ver)
self.__soft_path = '{}/pgsql/{}'.format(s_path)
# 获取配置项
def get_options(self, get):
data = {}
options = ['port', 'listen_addresses']
if not self.__soft_path: self.__soft_path = '{}/pgsql'.format(public.get_setup_path())
conf = public.readFile('{}/data/postgresql.conf'.format(self.__soft_path))
for opt in options:
tmp = re.findall(r"\s+" + opt + r"\s*=\s*(.+)#", conf)
if not tmp: continue;
data[opt] = tmp[0].strip()
if opt == 'listen_addresses':
data[opt] = data[opt].replace('\'', '')
data['password'] = self.get_root_pwd(None)['msg']
# return data
return public.return_message(0, 0, data)
def get_list(self, args):
"""
@获取数据库列表
@sql_type = pgsql
"""
# return self.get_base_list(args, sql_type = 'pgsql')
return public.return_message(0, 0, self.get_base_list(args, sql_type='pgsql'))
def get_sql_obj_by_sid(self, sid=0, conn_config=None):
"""
@取pgsql数据库对像 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 = panelPgsql()
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 = panelPgsql()
return db_obj
# return public.return_message(0, 0, db_obj)
def get_sql_obj(self, db_name):
"""
@取pgsql数据库对象
@db_name 数据库名称
"""
is_cloud_db = False
if db_name:
db_find = public.M('databases').where("name=?", db_name).find()
if db_find['sid']:
# return self.get_sql_obj_by_sid(db_find['sid'])
return public.return_message(0, 0, self.get_sql_obj_by_sid(db_find['sid']))
is_cloud_db = db_find['db_type'] in ['1', 1]
if is_cloud_db:
db_obj = panelPgsql()
conn_config = json.loads(db_find['conn_config'])
try:
db_obj = db_obj.set_host(conn_config['db_host'], conn_config['db_port'], conn_config['db_name'],
conn_config['db_user'], conn_config['db_password'])
except Exception as e:
raise public.PanelError(e)
else:
db_obj = panelPgsql()
# return db_obj
return public.return_message(0, 0, db_obj)
def GetCloudServer(self, args):
'''
@name 获取远程服务器列表
@author hwliang<2021-01-10>
@return list
'''
check_result = os.system('/www/server/pgsql/bin/psql --version')
if check_result != 0 and not public.M('database_servers').where('db_type=?', 'pgsql').count():
# return []
return public.return_message(0, 0, [])
# return self.GetBaseCloudServer(args)
return public.return_message(0, 0, self.GetBaseCloudServer(args))
def AddCloudServer(self, args):
'''
@添加远程数据库
'''
return self.AddBaseCloudServer(args)
# return public.return_message(0, 0, self.AddBaseCloudServer(args))
def RemoveCloudServer(self, args):
'''
@删除远程数据库
'''
return self.RemoveBaseCloudServer(args)
# return public.return_message(0, 0, self.RemoveBaseCloudServer(args))
def ModifyCloudServer(self, args):
'''
@修改远程数据库
'''
return self.ModifyBaseCloudServer(args)
def AddDatabase(self, args):
"""
@添加数据库
"""
# try:
if not args.get('name/str', 0):
# rreturn public.returnMsg(False, 'Database name cannot be empty!')
return public.return_message(-1, 0, 'Database name cannot be empty!')
import re
test_str = re.search(r"\W", args.name)
if test_str != None:
# rreturn public.returnMsg(False, 'The database name cannot contain special characters')
return public.return_message(-1, 0, 'The database name cannot contain special characters')
res = self.add_base_database(args)
if not res['status']:
# return res
return public.return_message(-1, 0, res['msg'])
data_name = res['data_name']
username = res['username']
password = res['data_pwd']
try:
self.sid = int(args['sid'])
except:
self.sid = 0
dtype = 'PgSql'
sql_obj = self.get_sql_obj_by_sid(self.sid)
result = sql_obj.execute("CREATE DATABASE {};".format(data_name))
isError = self.IsSqlError(result)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
# 添加用户
self.__CreateUsers(data_name, username, password, '127.0.0.1')
if not hasattr(args, 'ps'): args['ps'] = public.getMsg('INPUT_PS');
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
pid = 0
if hasattr(args, 'pid'): pid = args.pid
if hasattr(args, 'contact'):
site = public.M('sites').where("id=?", (args.contact,)).field('id,name').find()
if site:
pid = int(args.contact)
args['ps'] = site['name']
db_type = 0
if self.sid: db_type = 2
public.set_module_logs('pgsql', 'AddDatabase', 1)
# 添加入SQLITE
public.M('databases').add('pid,sid,db_type,name,username,password,accept,ps,addtime,type', (
pid, self.sid, db_type, data_name, username, password, '127.0.0.1', args['ps'], addTime, dtype))
public.WriteLog("TYPE_DATABASE", 'DATABASE_ADD_SUCCESS', (data_name,))
# return public.returnMsg(True,'ADD_SUCCESS')
return public.return_message(0, 0, 'ADD_SUCCESS')
# except Exception as ex:
# public.print_log("error info55: {}".format(ex))
# return public.return_message(-1, 0, str(ex))
def DeleteDatabase(self, get):
"""
@删除数据库
"""
id = get['id']
find = public.M('databases').where("id=?", (id,)).field(
'id,pid,name,username,password,accept,ps,addtime,db_type,conn_config,sid,type').find();
if not find:
# return public.returnMsg(False,'The specified database does not exist.')
return public.return_message(-1, 0, 'The specified database does not exist.')
name = get['name']
username = find['username']
sql_obj = self.get_sql_obj_by_sid(find['sid'])
result = sql_obj.execute("drop database {};".format(name))
sql_obj.execute("drop user {};".format(username))
# 删除SQLITE
public.M('databases').where("id=?", (id,)).delete()
public.WriteLog("TYPE_DATABASE", 'DATABASE_DEL_SUCCESS', (name,))
# return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_message(0, 0, 'DEL_SUCCESS')
def ToBackup(self, args):
"""
@备份数据库 id 数据库id
"""
id = args['id']
find = public.M('databases').where("id=?", (id,)).find()
if not find:
# return public.returnMsg(False,'Database does not exist!')
return public.return_message(-1, 0, 'Database does not exist!')
if not find['password'].strip():
# return public.returnMsg(False,'The database password is empty. Set the password first.')
return public.return_message(-1, 0, 'The database password is empty. Set the password first.')
sql_dump = '{}/bin/pg_dump'.format(self.__soft_path)
# return sql_dump
if not os.path.isfile(sql_dump):
# return public.returnMsg(False,'Lack of backup tools, please first through the software store PGSQL manager!')
return public.return_message(-1, 0,
'Lack of backup tools, please first through the software store PGSQL manager!')
back_path = session['config']['backup_path'] + '/database/pgsql/'
# return back_path
if not os.path.exists(back_path): os.makedirs(back_path)
fileName = find['name'] + '_' + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.sql'
backupName = back_path + fileName
if int(find['sid']):
info = self.get_info_by_db_id(id)
shell = '{} "host={} port={} user={} dbname={} password={}" > {}'.format(sql_dump, info['db_host'],
info['db_port'], info['db_user'],
find['name'], info['db_password'],
backupName)
else:
args_one = public.dict_obj()
port = self.get_port(args_one)
shell = '{} "host=127.0.0.1 port={} user={} dbname={} password={}" > {}'.format(sql_dump, port['data'],
find['username'],
find['name'],
find['password'],
backupName)
ret = public.ExecShell(shell)
if not os.path.exists(backupName):
# return public.returnMsg(False,'BACKUP_ERROR');
return public.return_message(-1, 0, 'BACKUP_ERROR')
public.M('backup').add('type,name,pid,filename,size,addtime',
(1, fileName, id, backupName, 0, time.strftime('%Y-%m-%d %X', time.localtime())))
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (find['name'],))
if os.path.getsize(backupName) < 2048:
# return public.returnMsg(True, 'The backup file size is smaller than 2Kb. Check the backup integrity.')
return public.return_message(0, 0, 'The backup file size is smaller than 2Kb. Check the backup integrity.')
else:
# return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_message(0, 0, 'BACKUP_SUCCESS')
def DelBackup(self, args):
"""
@删除备份文件
"""
return self.delete_base_backup(args)
# return public.return_message(0, 0, self.delete_base_backup(args))
def get_port(self, args): # 获取端口号
str_shell = '''netstat -luntp|grep postgres|head -1|awk '{print $4}'|awk -F: '{print $NF}' '''
try:
port = public.ExecShell(str_shell)[0]
if port.strip():
return {'data': port.strip(), "status": True}
else:
return {'data': 5432, "status": False}
except:
return {'data': 5432, "status": False}
# 导入
def InputSql(self, get):
name = get.name
file = get.file
# return name
find = public.M('databases').where("name=?", (name,)).find()
if not find:
# return public.returnMsg(False,'Database does not exist!')
return public.return_message(-1, 0, 'Database does not exist!')
# return find
if not find['password'].strip():
# return public.returnMsg(False,'The database password is empty. Set the password first.')
return public.return_message(-1, 0, 'The database password is empty. Set the password first.')
tmp = file.split('.')
exts = ['sql']
ext = tmp[len(tmp) - 1]
if ext not in exts:
# return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')
return public.return_message(-1, 0, 'DATABASE_INPUT_ERR_FORMAT')
sql_dump = '{}/bin/psql'.format(self.__soft_path)
if not os.path.exists(sql_dump):
# return public.returnMsg(False,'Lack of recovery tool, please use software management to install PGSQL!')
return public.return_message(-1, 0,
'Lack of recovery tool, please use software management to install PGSQL!')
if int(find['sid']):
info = self.get_info_by_db_id(find['id'])
shell = '{} "host={} port={} user={} dbname={} password={}" < {}'.format(sql_dump, info['db_host'],
info['db_port'], info['db_user'],
find['name'], info['db_password'],
file)
else:
args_one = public.dict_obj()
port = self.get_port(args_one)
shell = '{} "host=127.0.0.1 port={} user={} dbname={} password={}" < {}'.format(sql_dump, port['data'],
find['username'],
find['name'],
find['password'], file)
ret = public.ExecShell(shell)
public.WriteLog("TYPE_DATABASE", 'Description Succeeded in importing database [{}]'.format(name))
# return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS');
return public.return_message(0, 0, 'DATABASE_INPUT_SUCCESS')
def SyncToDatabases(self, get):
"""
@name同步数据库到服务器
"""
tmp_type = int(get['type'])
n = 0
sql = public.M('databases')
if tmp_type == 0:
where = "lower(type) = lower('pgsql')"
# data = sql.field('id,name,username,password,accept,type,sid,db_type').where('type=?',('pgsql',)).select()
data = sql.field('id,name,username,password,accept,type,sid,db_type').where(where, ()).select()
print(data)
for value in data:
if value['db_type'] in ['1', 1]:
continue # 跳过远程数据库
result = self.ToDataBase(value)
if result == 1: n += 1
else:
import json
data = json.loads(get.ids)
for value in data:
find = sql.where("id=?", (value,)).field('id,name,username,password,sid,db_type,accept,type').find()
result = self.ToDataBase(find)
if result == 1: n += 1
if n == 1:
# return public.returnMsg(True, 'Synchronization succeeded')
return public.return_message(0, 0, 'Synchronization succeeded')
elif n == 0:
# return public.returnMsg(False, 'Sync failed')
return public.return_message(-1, 0, 'Sync failed')
# return public.returnMsg(True, 'DATABASE_SYNC_SUCCESS', (str(n),))
return public.return_message(0, 0, 'DATABASE_SYNC_SUCCESS {}'.format(n))
def ToDataBase(self, find):
"""
@name 添加到服务器
"""
if find['username'] == 'bt_default': return 0
if len(find['password']) < 3:
find['username'] = find['name']
find['password'] = public.md5(str(time.time()) + find['name'])[0:10]
public.M('databases').where("id=?", (find['id'],)).save('password,username',
(find['password'], find['username']))
self.sid = find['sid']
sql_obj = self.get_sql_obj_by_sid(self.sid)
result = sql_obj.execute("CREATE DATABASE {};".format(find['name']))
isError = self.IsSqlError(result)
if isError != None and isError['status'] == False and isError[
'msg'] == 'The specified database already exists, please do not add it repeatedly.': return 1
self.__CreateUsers(find['name'], find['username'], find['password'], '127.0.0.1')
return 1
def SyncGetDatabases(self, get):
"""
@name 从服务器获取数据库
@param sid 0为本地数据库 1为远程数据库
"""
n = 0;
s = 0;
db_type = 0
self.sid = get.get('sid/d', 0)
if self.sid: db_type = 2
sql_obj = self.get_sql_obj_by_sid(self.sid)
data = sql_obj.query('SELECT datname FROM pg_database;') # select * from pg_database order by datname;
isError = self.IsSqlError(data)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
if type(data) == str:
# return public.returnMsg(False, data)
return public.return_message(-1, 0, data)
sql = public.M('databases')
nameArr = ['information_schema', 'postgres', 'template1', 'template0', 'performance_schema', 'mysql', 'sys',
'master', 'model', 'msdb', 'tempdb', 'ReportServerTempDB', 'YueMiao', 'ReportServer']
for item in data:
dbname = item[0]
if sql.where("name=?", (dbname,)).count(): continue
if not dbname in nameArr:
if sql.table('databases').add('name,username,password,accept,ps,addtime,type,sid,db_type', (
dbname, dbname, '', '', public.getMsg('INPUT_PS'), time.strftime('%Y-%m-%d %X', time.localtime()),
'pgsql', self.sid, db_type)): n += 1
# return public.returnMsg(True, 'DATABASE_GET_SUCCESS', (str(n),))
return public.return_message(0, 0, 'DATABASE_GET_SUCCESS {}'.format(n))
def ResDatabasePassword(self, args):
"""
@修改用户密码
"""
id = args['id']
username = args['name'].strip()
newpassword = public.trim(args['password'])
if not newpassword:
# return public.returnMsg(False, 'The database password cannot be empty.');
return public.return_message(-1, 0, 'The database password cannot be empty')
find = public.M('databases').where("id=?", (id,)).field(
'id,pid,name,username,password,type,accept,ps,addtime,sid').find()
if not find:
# return public.returnMsg(False, 'Modify the failureThe specified database does not exist.');
return public.return_message(-1, 0, 'Modify the failureThe specified database does not exist')
sql_obj = self.get_sql_obj_by_sid(find['sid'])
result = sql_obj.execute("alter user {} with password '{}';".format(username, newpassword))
isError = self.IsSqlError(result)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
# 修改SQLITE
public.M('databases').where("id=?", (id,)).setField('password', newpassword)
public.WriteLog("TYPE_DATABASE", 'DATABASE_PASS_SUCCESS', (find['name'],))
# return public.returnMsg(True, 'DATABASE_PASS_SUCCESS', (find['name'],))
return public.return_message(0, 0, 'DATABASE_PASS_SUCCESS {}'.format(find['name'],))
def get_root_pwd(self, args):
"""
@获取sa密码
"""
check_result = os.system('/www/server/pgsql/bin/psql --version')
if check_result != 0:
# return public.returnMsg(False,'If PgSQL is not installed or started, install or start it first')
return public.return_message(-1, 0,'If PgSQL is not installed or started, install or start it first')
password = ''
path = '{}/data/postgresAS.json'.format(public.get_panel_path())
if os.path.isfile(path):
try:
password = json.loads(public.readFile(path))['password']
print('333333333')
print(password)
except:
pass
if 'is_True' in args and args.is_True:
# return password
return public.return_message(-1, 0, password)
# return public.returnMsg(True, password)
return public.return_message(0, 0, password)
def set_root_pwd(self, args):
"""
@设置sa密码
"""
password = public.trim(args['password'])
if len(password) < 8:
# return public.returnMsg(False, 'The password must not be less than 8 digits.')
return public.return_message(-1, 0, 'The password must not be less than 8 digits.')
check_result = os.system('/www/server/pgsql/bin/psql --version')
if check_result != 0:
# return public.returnMsg(False,'If PgSQL is not installed or started, install or start it first')
return public.return_message(-1, 0, 'If PgSQL is not installed or started, install or start it first')
sql_obj = self.get_sql_obj_by_sid('0')
data = sql_obj.query('SELECT datname FROM pg_database;')
isError = self.IsSqlError(data)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
path = '{}/data/pg_hba.conf'.format(self.__soft_path)
p_path = '{}/data/postgresAS.json'.format(public.get_panel_path())
if not os.path.isfile(path):
# return public.returnMsg(False,'{}File does not exist, please check the installation is complete!'.format(path))
return public.return_message(-1, 0, '{}File does not exist, please check the installation is complete!'.format(path))
src_conf = public.readFile(path)
add_conf = src_conf.replace('md5', 'trust')
# public.writeFile(path,public.readFile(path).replace('md5','trust'))
public.writeFile(path, add_conf)
pg_obj = panelPgsql()
pg_obj.execute("ALTER USER postgres WITH PASSWORD '{}';".format(password))
data = {"username": "postgres", "password": ""}
try:
data = json.loads(public.readFile(p_path))
except:
pass
data['password'] = password
public.writeFile(p_path, json.dumps(data))
public.writeFile(path, src_conf)
# return public.returnMsg(True, 'The administrator password is successfully changed. Procedure.')
return public.return_message(0, 0, 'The administrator password is successfully changed. Procedure.')
def get_info_by_db_id(self, db_id):
"""
@获取数据库连接详情
@db_id 数据库id
"""
# print(db_id,'111111111111')
find = public.M('databases').where("id=?", db_id).find()
# return find
if not find: return False
# print(find)
data = {
'db_host': '127.0.0.1',
'db_port': 5432,
'db_user': find['username'],
'db_password': find['password']
}
if int(find['sid']):
conn_config = public.M('database_servers').where("id=?", find['sid']).find()
data['db_host'] = conn_config['db_host']
data['db_port'] = int(conn_config['db_port'])
return data
def get_database_size_by_id(self, args):
"""
@获取数据库尺寸(批量删除验证)
@args json/int 数据库id
"""
total = 0
db_id = args
if not isinstance(args, int): db_id = args['db_id']
try:
name = public.M('databases').where('id=?', db_id).getField('name')
sql_obj = self.get_sql_obj(name)
tables = sql_obj.query(
"select name,size,type from sys.master_files where type=0 and name = '{}'".format(name))
total = tables[0][1]
if not total: total = 0
except:
pass
return total
def check_del_data(self, args):
"""
@删除数据库前置检测
"""
# return self.check_base_del_data(args)
return public.return_message(0, 0, self.check_base_del_data(args))
# 本地创建数据库
def __CreateUsers(self, data_name, username, password, address):
"""
@创建数据库用户
"""
sql_obj = self.get_sql_obj_by_sid(self.sid)
sql_obj.execute("CREATE USER {} WITH PASSWORD '{}';".format(username, password))
sql_obj.execute("GRANT ALL PRIVILEGES ON DATABASE {} TO {};".format(data_name, username))
return True
def __get_db_list(self, sql_obj):
"""
获取pgsql数据库列表
"""
data = []
ret = sql_obj.query('SELECT datname FROM pg_database;')
if type(ret) == list:
for x in ret:
data.append(x[0])
return data
def check_cloud_database_status(self, conn_config):
"""
@检测远程数据库是否连接
@conn_config 远程数据库配置,包含host port pwd等信息
"""
try:
if not 'db_name' in conn_config: conn_config['db_name'] = None
sql_obj = panelPgsql().set_host(conn_config['db_host'], conn_config['db_port'], conn_config['db_name'],
conn_config['db_user'], conn_config['db_password'])
data = sql_obj.query("SELECT datname FROM pg_database;")
if type(data) == str:
# return public.returnMsg(False,'Connecting to remote PGSQL fails. Perform the following operations to rectify the fault<br/>1、The database port is correct and the firewall allows access<br/>2、Check whether the database account password is correct<br/>3、pg_hba.confWhether to add a client release record<br/>4、postgresql.conf Add listen_addresses to the correct server IP address.')
return public.return_message(-1, 0, 'Connecting to remote PGSQL fails. Perform the following operations to rectify the fault<br/>1、The database port is correct and the firewall allows access<br/>2、Check whether the database account password is correct<br/>3、pg_hba.confWhether to add a client release record<br/>4、postgresql.conf Add listen_addresses to the correct server IP address.')
if not conn_config['db_name']:
# return True
return public.return_message(0, 0, True)
for i in data:
if i[0] == conn_config['db_name']:
# return True
return public.return_message(0, 0, True)
# return public.returnMsg(False, 'The specified database does not exist!')
return public.return_message(-1, 0, 'The specified database does not exist!')
except Exception as ex:
# return public.returnMsg(False, ex)
return public.return_message(-1, 0, ex)
+611
View File
@@ -0,0 +1,611 @@
#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 databaseModelV2.base import databaseBase
import public
from public.validate import Param
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
'''
# # 校验参数
# try:
# args.validate([
# Param('type').Require().String('in', ['redis']),
# ], [
# public.validate.trim_filter(),
# ])
# except Exception as ex:
# public.print_log("error info: {}".format(ex))
# return public.return_message(-1, 0, str(ex))
# return self.GetBaseCloudServer(args)
return public.return_message(0, 0, self.GetBaseCloudServer(args))
def AddCloudServer(self,args):
'''
@添加远程数据库
'''
# {"db_host":"192.168.66.129","db_port":"6379","db_user":"root","db_password":"password1","db_ps":"192.168.66.129","type":"redis"}
# 校验参数
try:
args.validate([
Param('db_host').Require().Ip(),
Param('db_port').Require().Number(">=", 1).Number("<=", 65535),
Param('db_user').Require().String().Xss(),
Param('db_password').Require().String().Xss(),
Param('db_ps').Require().String(),
Param('type').Require().String().Xss(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
return self.AddBaseCloudServer(args)
# return public.return_message(0, 0, self.AddBaseCloudServer(args))
def RemoveCloudServer(self,args):
'''
@删除远程数据库
'''
return self.RemoveBaseCloudServer(args)
# return public.return_message(0, 0, self.RemoveBaseCloudServer(args))
def ModifyCloudServer(self,args):
'''
@修改远程数据库
'''
return self.ModifyBaseCloudServer(args)
# return public.return_message(0, 0, 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
"""
# 校验参数
try:
args.validate([
Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
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 Exception as ex:
public.print_log("error info2: {}".format(ex))
pass
#result = sorted(result,key= lambda x:x['keynum'],reverse=True)
# return result
return public.return_message(0, 0, result)
def set_redis_val(self,args):
"""
@设置或修改指定值
"""
# {"val":"bbbbbb12","endtime":"30","name":"aaaaa","db_idx":0,"sid":0}
# 校验参数
try:
args.validate([
Param('db_idx').Require().Integer(),
Param('sid').Require().Integer(),
Param('name').Require().String().Xss(), # 键
Param('val').Require().String().Xss(), # 值
Param('endtime').Integer(), # 过期时间
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
self.sid = args.get('sid/d',0)
if not 'name' in args or not 'val' in args:
# return public.returnMsg(False,'Parameter passing error.')
return public.return_message(-1, 0, '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,'Operation is successful.')
return public.return_message(0, 0, 'Operation is successful')
def del_redis_val(self,args):
"""
@删除key值
"""
# {"db_idx":0,"key":"qq","sid":0}
# 校验参数
try:
args.validate([
Param('db_idx').Require().Integer(),
Param('sid').Require().Integer(),
Param('key').Require().String().Xss(), # 键
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
self.sid = args.get('sid/d',0)
if not 'key' in args:
# return public.returnMsg(False,'Parameter passing error.')
return public.return_message(-1, 0, '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,'Operation is successful.')
return public.return_message(0, 0, 'Operation is successful')
def clear_flushdb(self,args):
"""
清空数据库
@ids 清空数据库列表,不传则清空所有
"""
# 校验参数
try:
args.validate([
Param('ids').String(), # "ids":"[0,1]"
Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
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,'Operation is successful.')
return public.return_message(0, 0, 'Operation is successful')
def get_db_keylist(self,args):
"""
@获取指定数据库key集合
"""
# 校验参数
try:
args.validate([
Param('db_type').Integer(),
Param('db_idx').Require().Integer(),
Param('limit').Integer(),
Param('p').Integer(),
Param('search').String(),
Param('tojs').String(), # 不知道
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
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
return public.return_message(0, 0, rdata)
def ToBackup(self,args):
"""
@备份数据库
"""
# 校验参数
try:
args.validate([
Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
try:
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,'BACKUP_ERROR')
return public.return_message(-1, 0, '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,'BACKUP_ERROR')
return public.return_message(-1, 0, 'BACKUP_ERROR')
# return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_message(0, 0, 'BACKUP_SUCCESS')
except Exception as ex:
public.print_log("error info22: {}".format(ex))
return public.return_message(-1, 0, str(ex))
def DelBackup(self,args):
"""
@删除备份文件
"""
# 校验参数
try:
args.validate([
Param('file').Require().SafePath(),
# Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
file = args.file
if os.path.exists(file):
os.remove(file)
# return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_message(0, 0, 'DEL_SUCCESS')
def InputSql(self,get):
"""
@导入数据库
"""
# 校验参数
try:
get.validate([
Param('file').Require().SafePath(),
Param('sid').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
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, 'Restore Successful.')
return public.return_message(0, 0, 'Restore Successful.')
# return public.returnMsg(False, 'Restore failure.')
return public.return_message(-1, 0, 'Restore failure.')
def get_backup_list(self,get):
"""
@获取备份文件列表
"""
# 校验参数
try:
get.validate([
Param('search').String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
search = ''
if hasattr(get, 'search'):
search = get['search'].strip().lower()
nlist = []
cloud_list = {}
# try:
# 修改返回后接口适配
listm = self.GetCloudServer({'type': 'redis'})
for x in listm['message']:
cloud_list['id-' + str(x['id'])] = x
path = session['config']['backup_path'] + '/database/redis/'
if not os.path.exists(path):
os.makedirs(path)
# except Exception as ex:
# public.print_log("error 扥就: {}".format(ex))
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
return public.return_message(0, 0, 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
return public.return_message(0, 0, True)
except Exception as ex:
# return public.returnMsg(False,ex)
return public.return_message(-1, 0, ex)
+22
View File
@@ -0,0 +1,22 @@
#coding: utf-8
#-------------------------------------------------------------------
# aaPanel
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
#-------------------------------------------------------------------
# Author: hwliang <hwl@aapanel.com>
#-------------------------------------------------------------------
#------------------------------
# sqlite模型
#------------------------------
import os,sys,re,json,shutil,psutil,time
from databaseModelV2.base import databaseBase
import public
class main(databaseBase):
def get_list(self,args):
return []
+667
View File
@@ -0,0 +1,667 @@
#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,time
from databaseModelV2.base import databaseBase
# import public,panelMssql
import public
import panel_mssql_v2 as panelMssql
from public.validate import Param
try:
from BTPanel import session
except :pass
class main(databaseBase):
def get_list(self,args):
"""
@获取数据库列表
@sql_type = sqlserver
"""
# {"table":"databases","search":"","limit":"10","p":1,"order":"username desc"}
# 校验参数
try:
args.validate([
Param('table').Require().String().Xss(),
Param('search').String(),
Param('order').String().Xss(),
Param('limit').Integer(),
Param('p').Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
# return self.get_base_list(args, sql_type = 'sqlserver')
return public.return_message(0, 0, self.get_base_list(args, sql_type = 'sqlserver'))
def get_mssql_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 = panelMssql.panelMssql()
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 = panelMssql.panelMssql()
return db_obj
def get_mssql_obj(self,db_name):
"""
@取mssql数据库对象
@db_name 数据库名称
"""
is_cloud_db = False
if db_name:
db_find = public.M('databases').where("name=?" ,db_name).find()
if db_find['sid']:
return self.get_mssql_obj_by_sid(db_find['sid'])
is_cloud_db = db_find['db_type'] in ['1',1]
if is_cloud_db:
db_obj = panelMssql.panelMssql()
conn_config = json.loads(db_find['conn_config'])
try:
db_obj = db_obj.set_host(conn_config['db_host'],conn_config['db_port'],conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
except Exception as e:
raise public.PanelError(e)
else:
db_obj = panelMssql.panelMssql()
return db_obj
def GetCloudServer(self,args):
'''
@name 获取远程服务器列表
@author hwliang<2021-01-10>
@return list
'''
# {"type":"sqlserver"}
# 校验参数
try:
args.validate([
Param('type').Require().String('in', ['sqlserver']),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
# return self.GetBaseCloudServer(args)
return public.return_message(0, 0, self.GetBaseCloudServer(args))
def AddCloudServer(self,args):
'''
@添加远程数据库
'''
return self.AddBaseCloudServer(args)
# return public.return_message(0, 0, self.AddBaseCloudServer(args))
def RemoveCloudServer(self,args):
'''
@删除远程数据库
'''
return self.RemoveBaseCloudServer(args)
# return public.return_message(0, 0, self.RemoveBaseCloudServer(args))
def ModifyCloudServer(self,args):
'''
@修改远程数据库
'''
return self.ModifyBaseCloudServer(args)
# return public.return_message(0, 0, self.ModifyBaseCloudServer(args))
def AddDatabase(self,args):
"""
@添加数据库
"""
# {"name":"test1","db_user":"test1","password":"nnMCp2ccJcBahJec","sid":"3","active":true,"ps":"test1","ssl":"REQUIRE SSL"}
# 校验参数
try:
args.validate([
Param('name').Require().String(),
Param('db_user').Require().String(),
Param('password').Require().String().Xss(),
Param('sid').Require().Integer(),
Param('active').Require().Bool(),
Param('ps').String(),
Param('ssl').String().Xss(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
try:
res = self.add_base_database(args)
if not res['status']:
# return res
return public.return_message(-1, 0, res['msg'])
data_name = res['data_name']
username = res['username']
password = res['data_pwd']
if re.match(r"^\d+",data_name):
# return public.returnMsg(False,'SQLServer databases cannot start with numbers!')
return public.return_message(-1, 0, 'SQLServer databases cannot start with numbers!')
reg_count = 0
regs = ['[a-z]','[A-Z]',r'\W','[0-9]']
for x in regs:
if re.search(x,password): reg_count += 1
if len(password) < 8 or len(password) >128 or reg_count < 3 :
# return public.returnMsg(False,'SQLServer password complexity policy does not match, should be 8-128 characters, and contain any 3 of them in upper case, lower case, digits, special symbols!')
return public.return_message(-1, 0, 'SQLServer password complexity policy does not match, should be 8-128 '
'characters, and contain any 3 of them in upper case, lower case, '
'digits, special symbols!')
try:
self.sid = int(args['sid'])
except :
self.sid = 0
dtype = 'SQLServer'
#添加SQLServer
mssql_obj = self.get_mssql_obj_by_sid(self.sid)
result = mssql_obj.execute("CREATE DATABASE %s" % data_name)
isError = self.IsSqlError(result)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
mssql_obj.execute("DROP LOGIN %s" % username)
#添加用户
self.__CreateUsers(data_name,username,password,'127.0.0.1')
if not hasattr(args,'ps'): args['ps'] = public.getMsg('INPUT_PS');
addTime = time.strftime('%Y-%m-%d %X',time.localtime())
pid = 0
if hasattr(args,'pid'): pid = args.pid
if hasattr(args,'contact'):
site = public.M('sites').where("id=?",(args.contact,)).field('id,name').find()
if site:
pid = int(args.contact)
args['ps'] = site['name']
db_type = 0
if self.sid: db_type = 2
public.set_module_logs('linux_sqlserver','AddDatabase',1)
#添加入SQLITE
public.M('databases').add('pid,sid,db_type,name,username,password,accept,ps,addtime,type',(pid,self.sid,db_type,data_name,username,password,'127.0.0.1',args['ps'],addTime,dtype))
public.WriteLog("TYPE_DATABASE", 'DATABASE_ADD_SUCCESS',(data_name,))
# return public.returnMsg(True,'ADD_SUCCESS')
return public.return_message(0, 0, 'ADD_SUCCESS')
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
def DeleteDatabase(self,args):
"""
@删除数据库
"""
# {"id":128,"name":"失去了23"}
# 校验参数
try:
args.validate([
Param('name').Require().String(),
Param('id').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
id = args['id']
find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid,db_type').find();
if not find:
# return public.returnMsg(False,'The specified database does not exist.')
return public.return_message(-1, 0, 'The specified database does not exist.')
name = args['name']
username = find['username']
mssql_obj = self.get_mssql_obj_by_sid(find['sid'])
mssql_obj.execute("ALTER DATABASE %s SET SINGLE_USER with ROLLBACK IMMEDIATE" % name)
result = mssql_obj.execute("DROP DATABASE %s" % name)
if self.get_database_size_by_id(find['sid']):
isError = self.IsSqlError(result)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
mssql_obj.execute("DROP LOGIN %s" % username)
#删除SQLITE
public.M('databases').where("id=?",(id,)).delete()
public.WriteLog("TYPE_DATABASE", 'DATABASE_DEL_SUCCESS',(name,))
# return public.returnMsg(True, 'DEL_SUCCESS')
return public.return_message(0, 0, 'DEL_SUCCESS')
def ToBackup(self,args):
"""
@备份数据库 id 数据库id
"""
id = args['id']
find = public.M('databases').where("id=?",(id,)).find()
if not find:
# return public.returnMsg(False,'Database does not exist!')
return public.return_message(-1, 0, 'Database does not exist!')
self.CheckBackupPath(args)
fileName = find['name'] + '_' + time.strftime('%Y%m%d_%H%M%S',time.localtime()) + '.bak'
backupName = session['config']['backup_path'] + '/database/sqlserver/' + fileName
mssql_obj = self.get_mssql_obj_by_sid(find['sid'])
if not int(find['sid']):
ret = mssql_obj.execute("backup database %s To disk='%s'" % (find['name'],backupName))
isError=self.IsSqlError(ret)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
else:
#远程数据库
# return public.returnMsg(False,'Operation failed. Remote database cannot be backed up.')
return public.return_message(-1, 0, 'Operation failed. Remote database cannot be backed up.')
if not os.path.exists(backupName):
# return public.returnMsg(False,'BACKUP_ERROR')
return public.return_message(-1, 0, 'BACKUP_ERROR')
public.M('backup').add('type,name,pid,filename,size,addtime',(1,fileName,id,backupName,0,time.strftime('%Y-%m-%d %X',time.localtime())))
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS",(find['name'],))
if os.path.getsize(backupName) < 2048:
# return public.returnMsg(True, 'The backup file size is smaller than 2Kb. Check the backup integrity.')
return public.return_message(0, 0, 'The backup file size is smaller than 2Kb. Check the backup integrity.')
else:
# return public.returnMsg(True, 'BACKUP_SUCCESS')
return public.return_message(0, 0, 'BACKUP_SUCCESS')
def DelBackup(self,args):
"""
@删除备份文件
"""
return self.delete_base_backup(args)
# return public.return_message(0, 0, self.delete_base_backup(args))
#导入
def InputSql(self,get):
# 校验参数
try:
get.validate([
Param('file').SafePath(), # 文件路径
Param('name').String(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
name = get.name
file = get.file
find = public.M('databases').where("name=?",(name,)).find()
if not find:
# return public.returnMsg(False,'Database does not exist!')
return public.return_message(-1, 0, 'Database does not exist!')
tmp = file.split('.')
exts = ['sql','zip','bak']
ext = tmp[len(tmp) -1]
if ext not in exts:
# return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')
return public.return_message(-1, 0, 'DATABASE_INPUT_ERR_FORMAT')
backupPath = session['config']['backup_path'] + '/database'
if ext == 'zip':
try:
fname = os.path.basename(file).replace('.zip','')
dst_path = backupPath + '/' +fname
if not os.path.exists(dst_path): os.makedirs(dst_path)
public.unzip(file,dst_path)
for x in os.listdir(dst_path):
if x.find('bak') >= 0 or x.find('sql') >= 0:
file = dst_path + '/' + x
break
except :
# return public.returnMsg(False,'The import failed because the file is not a valid ZIP file.')
return public.return_message(-1, 0, 'The import failed because the file is not a valid ZIP file.')
mssql_obj = self.get_mssql_obj_by_sid(find['sid'])
data = mssql_obj.query("use %s ;select filename from sysfiles" % find['name'])
isError = self.IsSqlError(data)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
if type(data) == str:
# return public.returnMsg(False,data)
return public.return_message(-1, 0, data)
mssql_obj.execute("ALTER DATABASE %s SET OFFLINE WITH ROLLBACK IMMEDIATE" % (find['name']))
mssql_obj.execute("use master;restore database %s from disk='%s' with replace, MOVE N'%s' TO N'%s',MOVE N'%s_Log' TO N'%s' " % (find['name'],file,find['name'],data[0][0],find['name'],data[1][0]))
mssql_obj.execute("ALTER DATABASE %s SET ONLINE" % (find['name']))
public.WriteLog("TYPE_DATABASE", 'Description Succeeded in importing database [{}]'.format(name))
# return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS')
return public.return_message(0, 0, 'DATABASE_INPUT_SUCCESS')
#同步数据库到服务器
def SyncToDatabases(self,get):
# 校验?
type = int(get['type'])
n = 0
sql = public.M('databases')
if type == 0:
data = sql.field('id,name,username,password,accept,type,sid,db_type').where('type=?',('SQLServer',)).select()
for value in data:
if value['db_type'] in ['1',1]:
continue # 跳过远程数据库
result = self.ToDataBase(value)
if result == 1: n +=1
else:
import json
data = json.loads(get.ids)
for value in data:
find = sql.where("id=?",(value,)).field('id,name,username,password,sid,db_type,accept,type').find()
result = self.ToDataBase(find)
if result == 1: n +=1
if n == 1:
# return public.returnMsg(True, 'Synchronization succeeded')
return public.return_message(0, 0, 'Synchronization succeeded')
elif n == 0:
# return public.returnMsg(False,'Sync failed')
return public.return_message(-1, 0, 'Sync failed')
# return public.returnMsg(True,'DATABASE_SYNC_SUCCESS',(str(n),))
return public.return_message(0, 0, 'DATABASE_SYNC_SUCCESS'.format(str(n)))
#添加到服务器
def ToDataBase(self,find):
if find['username'] == 'bt_default':
# return 0
return public.return_message(0, 0, 0)
if len(find['password']) < 3 :
find['username'] = find['name']
find['password'] = public.md5(str(time.time()) + find['name'])[0:10]
public.M('databases').where("id=?",(find['id'],)).save('password,username',(find['password'],find['username']))
self.sid = find['sid']
mssql_obj = self.get_mssql_obj_by_sid(self.sid)
result = mssql_obj.execute("CREATE DATABASE %s" % find['name'])
isError = self.IsSqlError(result)
if isError != None and not 'already exists' in result:
# return -1
return public.return_message(0, 0, -1)
self.__CreateUsers(find['name'],find['username'],find['password'],'127.0.0.1')
# return 1
return public.return_message(0, 0, 1)
#从服务器获取数据库
def SyncGetDatabases(self,get):
n = 0
s = 0
db_type = 0
self.sid = get.get('sid/d',0)
if self.sid: db_type = 2
mssql_obj = self.get_mssql_obj_by_sid(self.sid)
data = mssql_obj.query('SELECT name FROM MASTER.DBO.SYSDATABASES ORDER BY name')
isError = self.IsSqlError(data)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
if type(data) == str:
# return public.returnMsg(False,data)
return public.return_message(-1, 0, data)
sql = public.M('databases')
nameArr = ['information_schema','performance_schema','mysql','sys','master','model','msdb','tempdb','ReportServerTempDB','YueMiao','ReportServer']
for item in data:
dbname = item[0]
if sql.where("name=?",(dbname,)).count(): continue
if not dbname in nameArr:
if sql.table('databases').add('name,username,password,accept,ps,addtime,type,sid,db_type',(dbname,dbname,'','',public.getMsg('INPUT_PS'),time.strftime('%Y-%m-%d %X',time.localtime()),'SQLServer',self.sid,db_type)): n +=1
# return public.returnMsg(True,'DATABASE_GET_SUCCESS',(str(n),))
return public.return_message(0, 0, 'DATABASE_GET_SUCCESS'.format(n))
def ResDatabasePassword(self,args):
"""
@修改用户密码
"""
# 校验参数
try:
args.validate([
Param('password').Require().String().Xss(),
Param('name').Require().String(),
Param('id').Require().Integer(),
], [
public.validate.trim_filter(),
])
except Exception as ex:
public.print_log("error info: {}".format(ex))
return public.return_message(-1, 0, str(ex))
id = args['id']
username = args['name'].strip()
newpassword = public.trim(args['password'])
try:
# if not newpassword:
# return public.returnMsg(False, 'The password of database [' + username + '] cannot be empty.')
if len(re.search(r"^[\w@\.]+$", newpassword).groups()) > 0:
# return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
return public.return_message(-1, 0, 'The database password cannot be empty or contain special characters')
except :
# return public.returnMsg(False, 'The database password cannot be empty or contain special characters')
return public.return_message(-1, 0, 'The database password cannot be empty or contain special characters')
find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid').find()
if not find:
# return public.returnMsg(False, 'Modify the failureThe specified database does not exist.');
return public.return_message(-1, 0, 'Modify the failureThe specified database does not exist.')
mssql_obj = self.get_mssql_obj_by_sid(find['sid'])
mssql_obj.execute("EXEC sp_password NULL, '%s', '%s'" % (newpassword,username))
#修改SQLITE
public.M('databases').where("id=?",(id,)).setField('password',newpassword)
public.WriteLog("TYPE_DATABASE",'DATABASE_PASS_SUCCESS',(find['name'],))
# return public.returnMsg(True, 'DATABASE_PASS_SUCCESS',(find['name'],))
return public.return_message(0, 0, 'DATABASE_PASS_SUCCESS'.format(find['name']))
def get_root_pwd(self,args):
"""
@获取sa密码
"""
mssql_obj = panelMssql.panelMssql()
ret = mssql_obj.get_sql_name()
if not ret : return public.returnMsg(False, 'The SQL Server is not installed or started. Install or start it first')
sa_path = '{}/data/sa.pl'.format(public.get_panel_path())
if os.path.exists(sa_path):
password = public.readFile(sa_path)
return public.returnMsg(True,password)
return public.returnMsg(True,'')
def set_root_pwd(self,args):
"""
@设置sa密码
"""
password = public.trim(args['password'])
try:
if not password:
return public.returnMsg(False, 'The password of database [' + username + '] cannot be empty.')
if len(re.search(r"^[\w@\.]+$", password).groups()) > 0:
return public.returnMsg(False, 'saThe password cannot be empty or have special symbols')
except :
return public.returnMsg(False, 'saThe password cannot be empty or have special symbols')
mssql_obj = panelMssql.panelMssql()
result = mssql_obj.execute("EXEC sp_password NULL, '%s', 'sa'" % password)
isError = self.IsSqlError(result)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
public.writeFile('data/sa.pl',password)
session['config']['mssql_sa'] = password
return public.returnMsg(True,'The password of sa is changed successfully.')
def get_database_size_by_id(self,args):
"""
@获取数据库尺寸(批量删除验证)
@args json/int 数据库id
"""
total = 0
db_id = args
if not isinstance(args,int): db_id = args['db_id']
try:
name = public.M('databases').where('id=?',db_id).getField('name')
mssql_obj = self.get_mssql_obj(name)
tables = mssql_obj.query("select name,size,type from sys.master_files where type=0 and name = '{}'".format(name))
total = tables[0][1]
if not total: total = 0
except :pass
return total
def check_del_data(self,args):
"""
@删除数据库前置检测
"""
# {"ids": "[128]"}
# return self.check_base_del_data(args)
return public.return_message(0, 0, self.check_base_del_data(args))
#本地创建数据库
def __CreateUsers(self,data_name,username,password,address):
"""
@创建数据库用户
"""
mssql_obj = self.get_mssql_obj_by_sid(self.sid)
mssql_obj.execute("use %s create login %s with password ='%s' , default_database = %s" % (data_name,username,password,data_name))
mssql_obj.execute("use %s create user %s for login %s with default_schema=dbo" % (data_name,username,username))
mssql_obj.execute("use %s exec sp_addrolemember 'db_owner','%s'" % (data_name,data_name))
mssql_obj.execute("ALTER DATABASE %s SET MULTI_USER" % data_name)
#检测备份目录并赋值权限(MSSQL需要Authenticated Users
def CheckBackupPath(self,get):
backupFile = session['config']['backup_path'] + '/database/sqlserver'
if not os.path.exists(backupFile):
os.makedirs(backupFile)
get.filename = backupFile
get.user = 'Authenticated Users'
get.access = 2032127
import files
files.files().SetFileAccess(get)
def check_cloud_database_status(self,conn_config):
"""
@检测远程数据库是否连接
@conn_config 远程数据库配置,包含host port pwd等信息
"""
try:
import panelMssql
if not 'db_name' in conn_config: conn_config['db_name'] = None
sql_obj = panelMssql.panelMssql().set_host(conn_config['db_host'],conn_config['db_port'],conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
data = sql_obj.query("SELECT name FROM MASTER.DBO.SYSDATABASES ORDER BY name")
isError = self.IsSqlError(data)
if isError != None:
return isError
# return public.return_message(-1, 0, isError)
if type(data) == str:
# return public.returnMsg(False,data)
return public.return_message(-1, 0, data)
if not conn_config['db_name']:
# return True
return public.return_message(0, 0, True)
for i in data:
if i[0] == conn_config['db_name']:
# return True
return public.return_message(0, 0, True)
# return public.returnMsg(False,'The specified database does not exist!')
return public.return_message(-1, 0, 'The specified database does not exist!')
except Exception as ex:
# return public.returnMsg(False,ex)
return public.return_message(-1, 0, ex)