#!/usr/bin/env node // First configure the logger so it does not spam the console const logger = require('../lib/logger') logger.transports.forEach((transport) => { transport.level = 'warning' }) const models = require('../lib/models/') const readline = require('readline-sync') const minimist = require('minimist') function showUsage (tips) { console.log(`${tips} Command-line utility to create users for email-signin. Usage: bin/manage_users [--pass password] (--add | --del) user-email Options: --add\tAdd user with the specified user-email --del\tDelete user with specified user-email --reset\tReset user password with specified user-email --pass\tUse password from cmdline rather than prompting `) process.exit(1) } function getPass (argv, action) { // Find whether we use cmdline or prompt password if (typeof argv['pass'] !== 'string') { return readline.question(`Password for ${argv[action]}:`, { hideEchoBack: true }) } console.log('Using password from commandline...') return argv['pass'] } // Using an async function to be able to use await inside async function createUser (argv) { const existingUser = await models.User.findOne({ where: { email: argv['add'] } }) // Cannot create already-existing users if (existingUser !== undefined) { console.log(`User with e-mail ${existingUser.email} already exists! Aborting ...`) process.exit(1) } const pass = getPass(argv, 'add') // Lets try to create, and check success const ref = await models.User.create({ email: argv['add'], password: pass }) if (ref === undefined) { console.log(`Could not create user with email ${argv['add']}`) process.exit(1) } else { console.log(`Created user with email ${argv['add']}`) } } // Using an async function to be able to use await inside async function deleteUser (argv) { // Cannot delete non-existing users const existingUser = await models.User.findOne({ where: { email: argv['del'] } }) if (existingUser === undefined) { console.log(`User with e-mail ${argv['del']} does not exist, cannot delete`) process.exit(1) } // Sadly .destroy() does not return any success value with all // backends. See sequelize #4124 await existingUser.destroy() console.log(`Deleted user ${argv['del']} ...`) } // Using an async function to be able to use await inside async function resetUser (argv) { const existingUser = await models.User.findOne({ where: { email: argv['reset'] } }) // Cannot reset non-existing users if (existingUser === undefined) { console.log(`User with e-mail ${argv['reset']} does not exist, cannot reset`) process.exit(1) } const pass = getPass(argv, 'reset') // set password and save existingUser.password = pass await existingUser.save() console.log(`User with email ${argv['reset']} password has been reset`) } const options = { add: createUser, del: deleteUser, reset: resetUser } // Perform commandline-parsing const argv = minimist(process.argv.slice(2)) const keys = Object.keys(options) const opts = keys.filter((key) => argv[key] !== undefined) const action = opts[0] // Check for options missing if (opts.length === 0) { showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`) } // Check if both are specified if (opts.length > 1) { showUsage(`You cannot ${action.join(' and ')} at the same time!`) } // Check if not string if (typeof argv[action] !== 'string') { showUsage(`You must follow an email after --${action}`) } // Call respective processing functions options[action](argv).then(function () { process.exit(0) })