#!/usr/bin/env node /** * Module dependencies. */ const program = require('./commander'); const inquirer = require('inquirer'); const UsersService = require('../services/users'); const UserModel = require('../models/user'); const mongoose = require('../services/mongoose'); const util = require('./util'); const Table = require('cli-table'); const validateRequired = (msg = 'Field is required', len = 1) => (input) => { if (input && input.length >= len) { return true; } return msg; }; // Regeister the shutdown criteria. util.onshutdown([ () => mongoose.disconnect() ]); function getUserCreateAnswers(options) { if (options.flag_mode) { let user = { email: options.email, password: options.password, confirmPassword: options.password, username: options.name, roles: [] }; if (options.role && UserModel.USER_ROLES.indexOf(options.role) > -1) { user.roles = [options.role]; } return Promise.resolve(user); } return inquirer.prompt([ { name: 'email', message: 'Email', format: 'email', validate: validateRequired('Email is required') }, { name: 'password', message: 'Password', type: 'password', filter: (password) => { return UsersService .isValidPassword(password) .catch((err) => { throw err.message; }); } }, { name: 'confirmPassword', message: 'Confirm Password', type: 'password', filter: (confirmPassword) => { return UsersService .isValidPassword(confirmPassword) .catch((err) => { throw err.message; }); } }, { name: 'username', message: 'Username', filter: (username) => { return UsersService .isValidDisplayName(username) .catch((err) => { throw err.message; }); } }, { name: 'roles', message: 'User Role', type: 'checkbox', choices: UserModel.USER_ROLES } ]); } /** * Prompts for input and registers a user based on those. */ function createUser(options) { getUserCreateAnswers(options) .then((answers) => { if (answers.password !== answers.confirmPassword) { return Promise.reject(new Error('Passwords do not match')); } return answers; }) .then((answers) => { return UsersService .createLocalUser(answers.email.trim(), answers.password.trim(), answers.username.trim()) .then((user) => { console.log(`Created user ${user.id}.`); if (answers.roles.length > 0) { return Promise.all(answers.roles.map((role) => { return UsersService .addRoleToUser(user.id, role) .then(() => { console.log(`Added the role ${role} to User ${user.id}.`); }); })); } }); }) .then(() => { util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(); }); } /** * Deletes a user. */ function deleteUser(userID) { UserModel .findOneAndRemove({ id: userID }) .then(() => { console.log('Deleted user'); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(); }); } /** * Changes the password for a user. */ function passwd(userID) { inquirer.prompt([ { name: 'password', message: 'Password', type: 'password', validate: validateRequired('Password is required') }, { name: 'confirmPassword', message: 'Confirm Password', type: 'password', validate: validateRequired('Confirm Password is required') } ]) .then((answers) => { if (answers.password !== answers.confirmPassword) { return Promise.reject(new Error('Password mismatch')); } return UsersService.changePassword(userID, answers.password); }) .then(() => { console.log('Password changed.'); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Updates the user from the options array. */ function updateUser(userID, options) { const updates = []; if (options.email && typeof options.email === 'string' && options.email.length > 0) { let q = UserModel.update({ 'id': userID, 'profiles.provider': 'local' }, { $set: { 'profiles.$.id': options.email } }); updates.push(q); } if (options.name && typeof options.name === 'string' && options.name.length > 0) { let q = UserModel.update({ 'id': userID }, { $set: { username: options.name } }); updates.push(q); } Promise .all(updates.map((q) => q.exec())) .then(() => { console.log(`User ${userID} updated.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Lists all the users registered in the database. */ function listUsers() { UsersService .all() .then((users) => { let table = new Table({ head: [ 'ID', 'Username', 'Profiles', 'Roles', 'Status', 'State' ] }); users.forEach((user) => { table.push([ user.id, user.username, user.profiles.map((p) => p.provider).join(', '), user.roles.join(', '), user.status, user.disabled ? 'Disabled' : 'Enabled' ]); }); console.log(table.toString()); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Merges two users using the specified ID's. * @param {String} dstUserID id of the user to which is the target of the merge * @param {String} srcUserID id of the user to which is the source of the merge */ function mergeUsers(dstUserID, srcUserID) { UsersService .mergeUsers(dstUserID, srcUserID) .then(() => { console.log(`User ${srcUserID} was merged into user ${dstUserID}.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Adds a role to a user * @param {String} userUD id of the user to add the role to * @param {String} role the role to add */ function addRole(userID, role) { if (UserModel.USER_ROLES.indexOf(role) === -1) { console.error(`Role '${role}' is not supported. Supported roles are ${UserModel.USER_ROLES.join(', ')}.`); util.shutdown(1); return; } UsersService .addRoleToUser(userID, role) .then(() => { console.log(`Added the ${role} role to User ${userID}.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Removes a role from a user * @param {String} userUD id of the user to remove the role from * @param {String} role the role to remove */ function removeRole(userID, role) { if (UserModel.USER_ROLES.indexOf(role) === -1) { console.error(`Role '${role}' is not supported. Supported roles are ${UserModel.USER_ROLES.join(', ')}.`); util.shutdown(1); return; } UsersService .removeRoleFromUser(userID, role) .then(() => { console.log(`Removed the ${role} role from User ${userID}.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Ban a user * @param {String} userID id of the user to ban */ function ban(userID) { UsersService .setStatus(userID, 'BANNED') .then(() => { console.log(`Banned the User ${userID}.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Unban a user * @param {String} userUD id of the user to remove the role from */ function unban(userID) { UsersService .setStatus(userID, 'ACTIVE') .then(() => { console.log(`Unban the User ${userID}.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Disable a given user. * @param {String} userID the ID of a user to disable */ function disableUser(userID) { UsersService .disableUser(userID) .then(() => { console.log(`User ${userID} was disabled.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } /** * Enabled a given user. * @param {String} userID the ID of a user to enable */ function enableUser(userID) { UsersService .enableUser(userID) .then(() => { console.log(`User ${userID} was enabled.`); util.shutdown(); }) .catch((err) => { console.error(err); util.shutdown(1); }); } //============================================================================== // Setting up the program command line arguments. //============================================================================== program .command('create') .option('--email [email]', 'Email to use') .option('--password [password]', 'Password to use') .option('--name [name]', 'Name to use') .option('--role [role]', 'Role to add') .option('-f, --flag_mode', 'Source from flags instead of prompting') .description('create a new user') .action(createUser); program .command('delete ') .description('delete a user') .action(deleteUser); program .command('passwd ') .description('change a password for a user') .action(passwd); program .command('update ') .option('--email [email]', 'Email to use') .option('--name [name]', 'Name to use') .description('update a user') .action(updateUser); program .command('list') .description('list all the users in the database') .action(listUsers); program .command('merge ') .description('merge srcUser into the dstUser') .action(mergeUsers); program .command('addrole ') .description('adds a role to a given user') .action(addRole); program .command('removerole ') .description('removes a role from a given user') .action(removeRole); program .command('ban ') .description('ban a given user') .action(ban); program .command('uban ') .description('unban a given user') .action(unban); program .command('disable ') .description('disable a given user from logging in') .action(disableUser); program .command('enable ') .description('enable a given user from logging in') .action(enableUser); program.parse(process.argv); // If there is no command listed, output help. if (!process.argv.slice(2).length) { program.outputHelp(); util.shutdown(); }