admin-mongo
Version:
A Web user interface to administer MongoDB databases built using Express
288 lines (268 loc) • 10.9 kB
JavaScript
var _ = require('lodash');
var fs = require('fs');
var path = require('path');
// checks for the password in the /config/app.json file if it's set
exports.checkLogin = function(req, res, next){
var passwordConf = req.nconf.app.get('app');
// only check for login if a password is specified in the /config/app.json file
if(passwordConf && passwordConf.hasOwnProperty('password')){
// dont require login session for login route
if(req.path === '/app/login' || req.path === '/app/logout' || req.path === '/app/login_action'){
next();
}else{
// if the session exists we continue, else renter login page
if(req.session.loggedIn){
next(); // allow the next route to run
}else{
res.redirect(req.app_context + '/app/login');
}
}
}else{
// no password is set so we continue
next();
}
};
// gets some db stats
exports.get_db_status = function (mongo_db, cb){
var adminDb = mongo_db.admin();
adminDb.serverStatus(function (err, status){
if(err){
cb('Error', null);
}else{
cb(null, status);
}
});
};
// gets the backup dirs
exports.get_backups = function(cb){
var junk = require('junk');
var backupPath = path.join(__dirname, '../backups');
fs.readdir(backupPath, function (err, files){
cb(null, files.filter(junk.not));
});
};
// gets the db stats
exports.get_db_stats = function (mongo_db, db_name, cb){
var async = require('async');
var db_obj = {};
// if at connection level we loop db's and collections
if(db_name == null){
var adminDb = mongo_db.admin();
adminDb.listDatabases(function (err, db_list){
if(err){
cb('User is not authorised', null);
return;
}
if(db_list !== undefined){
async.forEachOf(exports.order_object(db_list.databases), function (value, key, callback){
exports.order_object(db_list.databases);
var skipped_dbs = ['null', 'admin', 'local'];
if(skipped_dbs.indexOf(value.name) === -1){
var tempDBName = value.name;
mongo_db.db(tempDBName).listCollections().toArray(function (err, coll_list){
var coll_obj = {};
async.forEachOf(exports.cleanCollections(coll_list), function (value, key, callback){
mongo_db.db(tempDBName).collection(value).stats(function (err, coll_stat){
coll_obj[value] = {Storage: coll_stat.size, Documents: coll_stat.count};
callback();
});
}, function (err){
if(err) console.error(err.message);
// add the collection object to the DB object with the DB as key
db_obj[value.name] = exports.order_object(coll_obj);
callback();
});
});
}else{
callback();
}
}, function (err){
if(err) console.error(err.message);
// wrap this whole thing up
cb(null, exports.order_object(db_obj));
});
}else{
// if doesnt have the access to get all DB's
cb(null, null);
}
});
// if at DB level, we just grab the collections below
}else{
mongo_db.db(db_name).listCollections().toArray(function (err, coll_list){
var coll_obj = {};
async.forEachOf(exports.cleanCollections(coll_list), function (value, key, callback){
mongo_db.db(db_name).collection(value).stats(function (err, coll_stat){
coll_obj[value] = {
Storage: coll_stat ? coll_stat.size : 0,
Documents: coll_stat ? coll_stat.count : 0
};
callback();
});
}, function (err){
if(err) console.error(err.message);
db_obj[db_name] = exports.order_object(coll_obj);
cb(null, db_obj);
});
});
}
};
// gets the Databases
exports.get_db_list = function (uri, mongo_db, cb){
var async = require('async');
var adminDb = mongo_db.admin();
var db_arr = [];
// if a DB is not specified in the Conn string we try get a list
if(uri.database === undefined || uri.database === null){
// try go all admin and get the list of DB's
adminDb.listDatabases(function (err, db_list){
if(db_list !== undefined){
async.forEachOf(db_list.databases, function (value, key, callback){
var skipped_dbs = ['null', 'admin', 'local'];
if(skipped_dbs.indexOf(value.name) === -1){
db_arr.push(value.name);
}
callback();
}, function (err){
if(err) console.error(err.message);
exports.order_array(db_arr);
cb(null, db_arr);
});
}else{
cb(null, null);
}
});
}else{
cb(null, null);
}
};
// Normally you would know how your ID's are stored in your DB. As the _id value which is used to handle
// all document viewing in adminMongo is a parameter we dont know if it is an ObjectId, string or integer. We can check if
// the _id string is a valid MongoDb ObjectId but this does not guarantee it is stored as an ObjectId in the DB. It's most likely
// the value will be an ObjectId (hopefully) so we try that first then go from there
exports.get_id_type = function (mongo, collection, doc_id, cb){
if(doc_id){
var ObjectID = require('mongodb').ObjectID;
// if a valid ObjectId we try that, then then try as a string
if(ObjectID.isValid(doc_id)){
mongo.collection(collection).findOne({_id: ObjectID(doc_id)}, function (err, doc){
if(doc){
// doc_id is an ObjectId
cb(null, {'doc_id_type': ObjectID(doc_id), 'doc': doc});
}else{
mongo.collection(collection).findOne({_id: doc_id}, function (err, doc){
if(doc){
// doc_id is string
cb(null, {'doc_id_type': doc_id, 'doc': doc});
}else{
cb('Document not found', {'doc_id_type': null, 'doc': null});
}
});
}
});
}else{
// if the value is not a valid ObjectId value we try as an integer then as a last resort, a string.
mongo.collection(collection).findOne({_id: parseInt(doc_id)}, function (err, doc){
if(doc){
// doc_id is integer
cb(null, {'doc_id_type': parseInt(doc_id), 'doc': doc});
return;
}else{
mongo.collection(collection).findOne({_id: doc_id}, function (err, doc){
if(doc){
// doc_id is string
cb(null, {'doc_id_type': doc_id, 'doc': doc});
}else{
cb('Document not found', {'doc_id_type': null, 'doc': null});
}
});
}
});
}
}else{
cb(null, {'doc_id_type': null, 'doc': null});
}
};
// gets the Databases and collections
exports.get_sidebar_list = function (mongo_db, db_name, cb){
var async = require('async');
var db_obj = {};
// if no DB is specified, we get all DBs and collections
if(db_name == null){
var adminDb = mongo_db.admin();
adminDb.listDatabases(function (err, db_list){
if(db_list){
async.forEachOf(db_list.databases, function (value, key, callback){
var skipped_dbs = ['null', 'admin', 'local'];
if(skipped_dbs.indexOf(value.name) === -1){
mongo_db.db(value.name).listCollections().toArray(function (err, collections){
collections = exports.cleanCollections(collections);
exports.order_array(collections);
db_obj[value.name] = collections;
callback();
});
}else{
callback();
}
}, function (err){
if(err) console.error(err.message);
cb(null, exports.order_object(db_obj));
});
}else{
cb(null, exports.order_object(db_obj));
}
});
}else{
mongo_db.db(db_name).listCollections().toArray(function (err, collections){
collections = exports.cleanCollections(collections);
exports.order_array(collections);
db_obj[db_name] = collections;
cb(null, db_obj);
});
}
};
// order the object by alpha key
exports.order_object = function(unordered){
if(unordered !== undefined){
var ordered = {};
var keys = Object.keys(unordered);
exports.order_array(keys);
keys.forEach(function (key){
ordered[key] = unordered[key];
});
}
return ordered;
};
exports.order_array = function(array){
if(array){
array.sort(function (a, b){
a = a.toLowerCase();
b = b.toLowerCase();
if(a === b)return 0;
if(a > b)return 1;
return-1;
});
}
return array;
};
// render the error page
exports.render_error = function(res, req, err, conn){
var connection_list = req.nconf.connections.get('connections');
var conn_string = '';
if(connection_list[conn] !== undefined){
conn_string = connection_list[conn].connection_string;
}
res.render('error', {
message: err,
conn: conn,
conn_string: conn_string,
connection_list: exports.order_object(connection_list),
helpers: req.handlebars.helpers
});
};
exports.cleanCollections = function(collection_list){
var list = [];
_.each(collection_list, function (item){
list.push(item.name);
});
return list;
};