Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using async in app startup script not returning any results

I am trying to run the following script in my Node app to check if any users exist and if not, create first admin user. Yet the script simply do nothing, return nothing even while using Try/Catch so can someone please tell me what I am missing / doing wrong here? or how I can possibly catch the error (if any)? Thanks

import pmongo from 'promised-mongo';
import crypto from 'crypto';

const salt = 'DuCDuUR8yvttLU7Cc4';

const MONGODB_URI = 'mongodb://localhost:27017/mydb';

const db = pmongo(MONGODB_URI, {
  authMechanism: 'ScramSHA1'
}, ['users']);


async function firstRunCheckAndCreateSuperAdmin(cb) {

  const username = '[email protected]';

  try {
     const user = await db.users.findOne({ role: 'admin'});
     console.log(user);
     if(!user) return cb('No user found');
  } catch(e) {
      cb('Unexpected error occurred');
  }

  if(!user) {
    console.log('No admin detected.');

    const adminPassword = crypto.pbkdf2Sync ( 'password', salt, 10000, 512, 'sha512' ).toString ( 'hex' );
    await db.users.update({username: username}, {$set: {username: username, password: adminPassword, role: 'admin'}}, {upsert: true});
  }

  db.close();
  process.exit();
}

firstRunCheckAndCreateSuperAdmin(function(err, resultA){
    if(err) console.log(err);
});
like image 781
MChan Avatar asked Jul 10 '17 19:07

MChan


3 Answers

You are not returning any callback when there is no admin user in the following code snippet

if (!user) {
    console.log('No admin detected.');

    const adminPassword = crypto.pbkdf2Sync ( 'password', salt, 10000, 512, 'sha512' ).toString ( 'hex' );
    await db.users.update({username: username}, {$set: {username: username, password: adminPassword, role: 'admin'}}, {upsert: true});

    // call cb(user) here
}
like image 154
Arpit Solanki Avatar answered Oct 31 '22 14:10

Arpit Solanki


Please see comment.

import pmongo from 'promised-mongo';
import crypto from 'crypto';

const salt = 'DuCDuUR8yvttLU7Cc4';

const MONGODB_URI = 'mongodb://localhost:27017/mydb';

const db = pmongo(MONGODB_URI, {
  authMechanism: 'ScramSHA1'
}, ['users']);


async function firstRunCheckAndCreateSuperAdmin(cb) {

  const username = '[email protected]';

  try {
    const user = await db.users.findOne({
      role: 'admin'
    });
    console.log(user);
    //(1) If user is undefined, then launch cb with an error message;
    if (!user) return cb('No user found');
  } catch (e) {
    //(2) If something is wrong, then launch cb with an error message;
    cb('Unexpected error occurred');
  }

  //This part of the code will only be reached if user is defined.
  //This is a dead code as if user is undefined, it would have exited at (1)
  if (!user) {
    console.log('No admin detected.');

    const adminPassword = crypto.pbkdf2Sync('password', salt, 10000, 512, 'sha512').toString('hex');
    await db.users.update({
      username: username
    }, {
      $set: {
        username: username,
        password: adminPassword,
        role: 'admin'
      }
    }, {
      upsert: true
    });
  }

  //So if user exists, it will close db and exit without calling cb.
  db.close();
  process.exit();
}

firstRunCheckAndCreateSuperAdmin(function(err, resultA) {
  if (err) console.log(err);
});

Note:

  • If you are using async/await, then you don't need to use callback.
  • If you are using callback, then you don't need to have a return statement.
  • If the intention of the function is suppose to have a return value, make sure all code path returns a value.
like image 45
Hin Fan Chan Avatar answered Oct 31 '22 14:10

Hin Fan Chan


I have tried to rewrite your code to make it smaller and to remove all node-style callback types of async code from it. I replaced update with insertOne since you only have one user to insert (not multiple to update). Also I have added 500 ms timeout when calling firstRunCheckAndCreateSuperAdmin in case it "hangs". It should log something at the end :)

import pmongo from 'promised-mongo'
import crypto from 'crypto'
import {
  promisify
} from 'util'

const pbkdf2 = promisify(crypto.pbkdf2)

const salt = 'DuCDuUR8yvttLU7Cc4'

const MONGODB_URI = 'mongodb://localhost:27017/mydb'

const db = pmongo(MONGODB_URI, {
  authMechanism: 'ScramSHA1'
}, ['users']);

const username = '[email protected]'

async function firstRunCheckAndCreateSuperAdmin() {
  let user = await db.users.findOne({
    role: 'admin'
  });

  if (!user) { // no user lets create one
    user = await db.users.insertOne({
      username: username,
      password: (await pbkdf2('password', salt, 10000, 512, 'sha512')).toString('HEX'),
      role: 'admin'
    });
  }

  return user
}

const timeout = delay => message => new Promise((_, reject) => setTimeout(reject, delay, new Error(message)))

Promise
  .race([firstRunCheckAndCreateSuperAdmin(), timeout(500)('Rejected due to timeout')])
  .then(user => console.log(`Got user ${JSON.stringify(user)}`))
  .catch(error => console.error(error))
like image 30
Yury Tarabanko Avatar answered Oct 31 '22 12:10

Yury Tarabanko