UNPKG

admin-mongo

Version:

A Web user interface to administer MongoDB databases built using Express

288 lines (268 loc) 10.9 kB
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; };