webgme-engine
Version:
WebGME server and Client API without a GUI
205 lines (169 loc) • 6.95 kB
JavaScript
/*eslint-env node*/
/*eslint no-console: 0*/
/**
* @author lattmann / https://github.com/lattmann
*/
;
var main;
main = function (argv, callback) {
var path = require('path'),
gmeConfig = require(path.join(process.cwd(), 'config')),
mongodb = require('mongodb'),
Q = require('q'),
webgme = require('../../index'),
StorageUtil,
Command = require('commander').Command,
logger = webgme.Logger.create('gme:bin:migrateprojects', gmeConfig.bin.log),
program = new Command(),
dryRun,
gmeAuth,
users,
error,
db;
callback = callback || function () {
};
webgme.addToRequireJsPaths(gmeConfig);
StorageUtil = webgme.requirejs('common/storage/util');
program.option('-f, --force', 'Migrate all projects.');
program.parse(argv);
if (program.force) {
dryRun = false;
logger.info('Database will be updated.');
} else {
dryRun = true;
logger.warn('Before you run this script with a database update, it is strongly recommended to do a mongodump.');
logger.info('Dry run, please add -f as a command line argument if you like to update the database.');
}
logger.info('Connecting to database: ' + gmeConfig.mongo.uri);
webgme.getGmeAuth(gmeConfig)
.then(function (gmeAuth_) {
gmeAuth = gmeAuth_;
return gmeAuth.listUsers();
})
.then(function (users_) {
users = users_;
return Q.ninvoke(mongodb.MongoClient, 'connect', gmeConfig.mongo.uri, gmeConfig.mongo.options);
})
.then(function (db_) {
db = db_;
logger.debug('Connected to database: ' + gmeConfig.mongo.uri);
return getProjects();
})
.then(function (upgradeInfo) {
upgradeInfo.map(function (detail) {
// print out upgrade details.
logger.info(detail.collectionName + ' will be owned by ' + detail.owner);
});
if (dryRun) {
return Q.resolve();
} else {
return doUpgrade(upgradeInfo);
}
})
.then(function () {
if (dryRun) {
logger.warn('Database did not get migrated. This was only a dry run.');
} else {
logger.info('Database got migrated.');
}
})
.catch(function (err) {
error = err;
logger.error('Script execution failed.', error);
})
.finally(function () {
logger.debug('Closing database: ' + gmeConfig.mongo.uri);
Q.all([
gmeAuth.unload(),
Q.ninvoke(db, 'close')
])
.catch(function (err) {
error = error || err;
logger.error(err);
})
.finally(function () {
callback(error);
});
});
function getProjects(cb) {
logger.info('Fetching old projects and their information ...');
return Q.ninvoke(db, 'collectionNames')
.then(function (collections) {
var upgradeInfo = [],
projectDetail;
// discover old projects
collections.map(function (collection) {
if (collection.name === 'system.indexes' ||
collection.name.indexOf('_') === 0 ||
collection.name.indexOf('+') > -1) {
logger.warn('Project/collection will not be migrated: ' + collection.name);
} else {
// good old project name
projectDetail = {
collectionName: collection.name,
owner: null
};
// get existing authorization information for old project
users.map(function (user) {
// identify possible owner of the project
if (Object.hasOwn(user.projects, collection.name) &&
user.projects[collection.name].delete) {
if (projectDetail.owner) {
// owner is already selected
} else {
projectDetail.owner = user._id;
}
}
});
if (projectDetail.owner === null) {
projectDetail.owner = gmeConfig.authentication.guestAccount;
logger.warn(projectDetail.collectionName +
' Project was owned nobody, assigning it to guest account: ' +
projectDetail.owner);
}
upgradeInfo.push(projectDetail);
}
});
return Q.resolve(upgradeInfo);
})
.nodeify(cb);
}
function doUpgrade(upgradeInfo) {
var promises = [],
promise;
upgradeInfo.map(function (info) {
var newProjectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(info.owner, info.collectionName);
promise = Q.ninvoke(db, 'collection', info.collectionName)
.then(function (collection) {
return Q.ninvoke(collection, 'rename', newProjectId);
})
.then(function () {
return gmeAuth.addProject(info.owner, info.collectionName, {} /*info*/);
})
.then(function () {
var authorizePromises = [],
authorizePromise;
users.map(function (user) {
if (Object.hasOwn(user.projects, info.collectionName)) {
logger.info('Authorizing ' + user._id + ' for ' + newProjectId);
authorizePromise = gmeAuth.authorizeByUserId(user._id, newProjectId, 'create',
user.projects[info.collectionName])
.then(function () {
return gmeAuth.authorizeByUserId(user._id, info.collectionName, 'delete');
});
authorizePromises.push(authorizePromise);
}
});
return Q.allSettled(authorizePromises);
});
promises.push(promise);
});
return Q.allSettled(promises);
}
};
module.exports = {
main: main
};
if (require.main === module) {
main(process.argv);
}