This commit is contained in:
Mr Chen
2024-05-03 12:05:02 +08:00
parent 8c4820046a
commit 4ee5e41882
5 changed files with 394 additions and 30 deletions
+34
View File
@@ -15,6 +15,39 @@
.inlineBlock {
display: inline-block;
}
.db_list{
padding: 0px 0 10px 0;
font-size: 13px;
line-height: 35px;
height: 45px;
}
.db_list a{
margin-right: 15px;
color: #555;
font-weight: 600;
}
.db_list span:nth-child(1){
display: block;
float: left;
padding-left: 15px;
background: #ececec;
border-radius: 3px;
}
#db_tools button {
margin-right: 10px;
}
#db_tools button:last-child{
margin-right: 0;
}
.conf_p span {
display: inline-block;
margin-right: 10px;
width: 115px;
text-align: right;
}
</style>
<div class="bt-form">
@@ -40,6 +73,7 @@
<script type="text/javascript">
//mongodb start
resetPluginWinHeight(530);
resetPluginWinWidth(800);
$.getScript('/plugins/file?name=mongodb&f=js/mongodb.js', function(){
pluginService('mongodb');
});
+150 -6
View File
@@ -310,12 +310,7 @@ def saveConfig():
reload()
return mw.returnJson(True,'设置成功')
# print(mg_pass)
# listDbs = client.admin.command({"listDatabases": 1})
# print(listDbs)
# print(client_pass.list_database_names());
def initMgRoot(password='',force=0):
if force == 1:
d = getConfigData()
auth_t = d['security']['authorization']
@@ -552,6 +547,10 @@ def addDb():
if not data_name:
return mw.returnJson(False, "数据库名不能为空!")
nameArr = ['admin', 'config', 'local']
if data_name in nameArr:
return mw.returnJson(False, "数据库名是保留名称!")
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
username = ''
password = ''
@@ -569,7 +568,7 @@ def addDb():
client[data_name].chat.insert_one({})
user_roles = [{'role': 'dbOwner', 'db': data_name}, {'role': 'userAdmin', 'db': data_name}]
if auth_status:
db.command("dropUser", username)
# db.command("dropUser", username)
db.command("createUser", username, pwd=password, roles=user_roles)
ps = args['ps']
@@ -581,6 +580,35 @@ def addDb():
return mw.returnJson(True, '添加成功')
def delDb():
client = mongdbClient()
db = client.admin
sqlite_db = pSqliteDb('databases')
args = getArgs()
data = checkArgs(args, ['id', 'name'])
if not data[0]:
return data[1]
try:
sid = args['id']
name = args['name']
find = sqlite_db.where("id=?", (sid,)).field('id,name,username,password,accept,ps,addtime').find()
accept = find['accept']
username = find['username']
client.drop_database(name)
try:
db.command('dropUser',username)
except Exception as e:
pass
# 删除SQLITE
sqlite_db.where("id=?", (sid,)).delete()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def setRootPwd(version=''):
args = getArgs()
data = checkArgs(args, ['password'])
@@ -602,6 +630,112 @@ def setRootPwd(version=''):
except Exception as ex:
return mw.returnJson(False, '修改错误:' + str(ex))
def setUserPwd(version=''):
client = mongdbClient()
db = client.admin
sqlite_db = pSqliteDb('databases')
args = getArgs()
data = checkArgs(args, ['password', 'name'])
if not data[0]:
return data[1]
newpassword = args['password']
username = args['name']
uid = args['id']
try:
name = sqlite_db.where('id=?', (uid,)).getField('name')
user_roles = [{'role': 'dbOwner', 'db': name}, {'role': 'userAdmin', 'db': name}]
try:
db.command("updateUser", username, pwd=newpassword, roles=user_roles)
except Exception as e:
db.command("createUser", username, pwd=newpassword, roles=user_roles)
sqlite_db.where("id=?", (uid,)).setField('password', newpassword)
return mw.returnJson(True, mw.getInfo('修改数据库[{1}]密码成功!', (name,)))
except Exception as ex:
return mw.returnJson(False, mw.getInfo('修改数据库[{1}]密码失败[{2}]!', (name, str(ex),)))
def syncGetDatabases():
client = mongdbClient()
sqlite_db = pSqliteDb('databases')
db = client.admin
data = client.admin.command({"listDatabases": 1})
nameArr = ['admin', 'config', 'local']
n = 0
for value in data['databases']:
vdb_name = value["name"]
b = False
for key in nameArr:
if vdb_name == key:
b = True
break
if b:
continue
if sqlite_db.where("name=?", (vdb_name,)).count() > 0:
continue
host = '127.0.0.1'
ps = vdb_name
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
if sqlite_db.add('name,username,password,accept,ps,addtime', (vdb_name, vdb_name, '', host, ps, addTime)):
n += 1
msg = mw.getInfo('本次共从服务器获取了{1}个数据库!', (str(n),))
return mw.returnJson(True, msg)
def setDbPs():
args = getArgs()
data = checkArgs(args, ['id', 'name', 'ps'])
if not data[0]:
return data[1]
ps = args['ps']
sid = args['id']
name = args['name']
try:
psdb = pSqliteDb('databases')
psdb.where("id=?", (sid,)).setField('ps', ps)
return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注成功!', (name,)))
except Exception as e:
return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注失败!', (name,)))
def getDbInfo():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
ret = {}
client = mongdbClient()
db_name = args['name']
db = client[db_name]
result = db.command("dbStats")
result["collection_list"] = []
for collection_name in db.list_collection_names():
collection = db.command("collStats", collection_name)
data = {
"collection_name": collection_name,
"count": collection.get("count"), # 文档数
"size": collection.get("size"), # 内存中的大小
"avg_obj_size": collection.get("avgObjSize"), # 对象平均大小
"storage_size": collection.get("storageSize"), # 存储大小
"capped": collection.get("capped"),
"nindexes": collection.get("nindexes"), # 索引数
"total_index_size": collection.get("totalIndexSize"), # 索引大小
}
result["collection_list"].append(data)
return mw.returnJson(True,'ok', result)
def testData():
'''
cd /www/server/mdserver-web && source bin/activate && python3 /www/server/mdserver-web/plugins/mongodb/index.py test_data
@@ -788,8 +922,18 @@ if __name__ == "__main__":
print(getDbList())
elif func == 'add_db':
print(addDb())
elif func == 'del_db':
print(delDb())
elif func == 'set_root_pwd':
print(setRootPwd())
elif func == 'set_user_pwd':
print(setUserPwd())
elif func == 'sync_get_databases':
print(syncGetDatabases())
elif func == 'set_db_ps':
print(setDbPs())
elif func == 'get_db_info':
print(getDbInfo())
elif func == 'run_log':
print(runLog())
elif func == 'test':
+205 -23
View File
@@ -26,6 +26,18 @@ function mgPost(method, version, args,callback){
},'json');
}
function mgAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
return syncPost('/plugins/run', {name:'mongodb', func:method, args:_args});
}
function mongoStatus() {
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@@ -38,7 +50,7 @@ function mongoStatus() {
var rdata = $.parseJSON(data.data);
var con = '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 490px;">\
<table class="table table-hover table-bordered" style="width: 660px;">\
<thead><th>字段</th><th>当前值</th><th>说明</th></thead>\
<tbody>\
<tr><th>host</th><td>' + rdata.host + '</td><td>服务器</td></tr>\
@@ -87,7 +99,7 @@ function mongoDocStatus() {
// console.log(t);
var con = '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 490px;">\
<table class="table table-hover table-bordered" style="width: 660px;">\
<thead><th>库名</th><th>大小</th><th>存储大小</th><th>数据</th><th>索引</th><th>文档数据</th><th>对象</th></thead>\
<tbody>'+t+'<tbody>\
</table></div>';
@@ -121,7 +133,7 @@ function mongoReplStatus() {
}
var con = '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 490px;">\
<table class="table table-hover table-bordered" style="width: 660px;">\
<thead><th>字段</th><th>当前值</th><th>说明</th></thead>\
<tbody>\
'+tbody+'\
@@ -222,27 +234,8 @@ function dbList(page, search){
list += '<a href="javascript:;" class="btlink" class="btlink" onclick="setBackup(\''+rdata.data[i]['name']+'\',this)" title="数据库备份">'+(rdata.data[i]['is_backup']?'备份':'未备份') +'</a> | ';
var rw = '';
var rw_change = 'all';
if (typeof(rdata.data[i]['rw'])!='undefined'){
var rw_val = '读写';
if (rdata.data[i]['rw'] == 'all'){
rw_val = "所有";
rw_change = 'rw';
} else if (rdata.data[i]['rw'] == 'rw'){
rw_val = "读写";
rw_change = 'r';
} else if (rdata.data[i]['rw'] == 'r'){
rw_val = "只读";
rw_change = 'all';
}
rw = '<a href="javascript:;" class="btlink" onclick="setDbRw(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\',\''+rw_change+'\')" title="设置读写">'+rw_val+'</a> | ';
}
list += '<a href="javascript:;" class="btlink" onclick="repTools(\''+rdata.data[i]['name']+'\')" title="MySQL优化修复工具">工具</a> | ' +
'<a href="javascript:;" class="btlink" onclick="setDbAccess(\''+rdata.data[i]['username']+'\')" title="设置数据库权限">权限</a> | ' +
rw +
'<a href="javascript:;" class="btlink" onclick="setDbPass('+rdata.data[i]['id']+',\''+ rdata.data[i]['username'] +'\',\'' + rdata.data[i]['password'] + '\')">改密</a> | ' +
'<a href="javascript:;" class="btlink" onclick="delDb(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\')" title="删除数据库">删除</a>' +
'</td>';
@@ -250,10 +243,10 @@ function dbList(page, search){
}
//<button onclick="" id="dataRecycle" title="删除选中项" class="btn btn-default btn-sm" style="margin-left: 5px;"><span class="glyphicon glyphicon-trash" style="margin-right: 5px;"></span>回收站</button>
// <button onclick="setDbAccess(\'root\')" title="ROOT权限" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">ROOT权限</button>\
var con = '<div class="safe bgw">\
<button onclick="addDatabase()" title="添加数据库" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加数据库</button>\
<button onclick="setRootPwd(0,\''+rdata.info['root_pwd']+'\')" title="设置Mongodb管理员密码" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">root密码</button>\
<button onclick="setDbAccess(\'root\')" title="ROOT权限" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">ROOT权限</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\
@@ -418,3 +411,192 @@ function setRootPwd(type, pwd){
});
}
function syncGetDatabase(){
mgPost('sync_get_databases', '', '', function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
},{ icon: rdata.status ? 1 : 2 });
});
}
function showHidePass(obj){
var a = "glyphicon-eye-open";
var b = "glyphicon-eye-close";
if($(obj).hasClass(a)){
$(obj).removeClass(a).addClass(b);
$(obj).prev().text($(obj).prev().attr('data-pw'))
}
else{
$(obj).removeClass(b).addClass(a);
$(obj).prev().text('***');
}
}
function setDbPs(id, name, obj) {
var _span = $(obj);
var _input = $("<input class='baktext' value=\""+_span.text()+"\" type='text' placeholder='备注信息' />");
_span.hide().after(_input);
_input.focus();
_input.blur(function(){
$(this).remove();
var ps = _input.val();
_span.text(ps).show();
var data = {name:name,id:id,ps:ps};
mgPost('set_db_ps', '',data, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
});
_input.keyup(function(){
if(event.keyCode == 13){
_input.trigger('blur');
}
});
}
function delDb(id, name){
safeMessage('删除['+name+']','您真的要删除['+name+']吗?',function(){
var data='id='+id+'&name='+name;
mgPost('del_db', '', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
}
function delDbBatch(){
var arr = [];
$('input[type="checkbox"].check:checked').each(function () {
var _val = $(this).val();
var _name = $(this).parent().next().text();
if (!isNaN(_val)) {
arr.push({'id':_val,'name':_name});
}
});
safeMessage('批量删除数据库','<a style="color:red;">您共选择了[2]个数据库,删除后将无法恢复,真的要删除吗?</a>',function(){
var i = 0;
$(arr).each(function(){
var data = mgAsyncPost('del_db', this);
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']});
}
i++;
});
var msg = '成功删除['+i+']个数据库!';
showMsg(msg,function(){
dbList();
},{icon: 1}, 600);
});
}
function setDbPass(id, username, password){
layer.open({
type: 1,
area: '500px',
title: '修改数据库密码',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='mod_pwd'>\
<div class='line'>\
<span class='tname'>用户名</span>\
<div class='info-r'><input readonly='readonly' name=\"name\" class='bt-input-text mr5' type='text' style='width:330px;outline:none;' value='"+username+"' /></div>\
</div>\
<div class='line'>\
<span class='tname'>密码</span>\
<div class='info-r'>\
<input class='bt-input-text mr5' type='text' name='password' id='MyPassword' style='width:330px' value='"+password+"' />\
<span title='随机密码' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span></div>\
</div>\
<input type='hidden' name='id' value='"+id+"'>\
</form>",
yes:function(index){
// var data = $("#mod_pwd").serialize();
var data = {};
data['name'] = $('input[name=name]').val();
data['password'] = $('#MyPassword').val();
data['id'] = $('input[name=id]').val();
mgPost('set_user_pwd', '',data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
layer.close(index);
dbList();
},{icon: rdata.status ? 1 : 2});
});
}
});
}
function repTools(db_name, res){
mgPost('get_db_info', '', {name:db_name}, function(data){
var rdata = $.parseJSON(data.data);
var rdata = rdata.data;
console.log(rdata.collection_list);
var tbody = '';
for (var i = 0; i < rdata.collection_list.length; i++) {
tbody += '<tr>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].collection_name + '</span></td>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].count + '</span></td>\
<td>' + toSize(rdata.collection_list[i].size) + '</td>\
<td><span style="width:90px;"> ' + toSize(rdata.collection_list[i].avg_obj_size) + '</span></td>\
<td>' + toSize(rdata.collection_list[i].storage_size) + '</td>\
<td>' + rdata.collection_list[i].nindexes + '</td>\
<td>' + toSize(rdata.collection_list[i].total_index_size) + '</td>\
</tr> '
}
if (res) {
$(".gztr").html(tbody);
$("#db_tools").html('');
$("input[type='checkbox']").attr("checked", false);
$(".tools_size").html('大小:' + rdata.data_size);
return;
}
layer.open({
type: 1,
title: "MongoDB工具箱【" + db_name + "】",
area: ['780px', '480px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<span><a>数据库名称:'+ db_name + '</a>\
<a>集合:'+ rdata.collections + '</a>\
<a class="tools_size">存储大小:'+ toSize(rdata.storageSize) + '</a>\
<a class="tools_size">索引大小:'+ toSize(rdata.indexSize) + '</a>\
</span>\
<span id="db_tools" style="float: right;"></span>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:360px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>集合名称</th>\
<th>文档数量</th>\
<th>内存中的大小</th>\
<th>对象平均大小</th>\
<th>存储大小</th>\
<th>索引数量</th>\
<th>索引大小</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
</div>'
});
tableFixed('database_fix');
});
}