Meggy
Meggy

Reputation: 1671

NodeJS Sequelize - Fetch the ID from the row just created in MySQL?

Currently, my code returns a message which says 'Registration successful'. How can I return the id of the row I just created in MySQL instead?

function register(req, res, next) { 
    accountService.register(req.body, req.get('origin'))
        .then(() => res.json({ message: 'Registration successful' }))
        .catch(next);
}

Here's the model;

const { DataTypes } = require('sequelize');

module.exports = model;

function model(sequelize) {
    const attributes = {
        id: {type: Sequelize.INTEGER,primaryKey:true,autoIncrement: true,allowNull: false},
        email: { type: DataTypes.STRING, allowNull: false },
        passwordHash: { type: DataTypes.STRING, allowNull: false },
        name: { type: DataTypes.STRING, allowNull: false },
        gavatar: { type: DataTypes.STRING, allowNull: false },               
        role: { type: DataTypes.STRING, allowNull: false },
        verificationToken: { type: DataTypes.STRING },
        verified: { type: DataTypes.DATE },
        resetToken: { type: DataTypes.STRING },
        resetTokenExpires: { type: DataTypes.DATE },
        passwordReset: { type: DataTypes.DATE },
        created: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
        updated: { type: DataTypes.DATE },      
        isVerified: {
            type: DataTypes.VIRTUAL,
            get() { return !!(this.verified || this.passwordReset); }
        }
    };

    const options = {
        timestamps: false, 
        defaultScope: {
             attributes: { exclude: ['passwordHash'] }
        },
        scopes: {
            withHash: { attributes: {}, }
        }        
    };

    return sequelize.define('account', attributes, options);
}

I tried this;

accountService.register(req.body,req.get('origin')).then(()=>res.json(account.id))

But I got an error which said;

"message":"Cannot read property 'findOne' of undefined"

Here's the register function in the account.service.js;

async function register(params, origin) {
  
    if (await db.Account.findOne({ where: { email: params.email } })) {
        return await sendAlreadyRegisteredEmail(params.email, origin);
    }

    const account = new db.Account(params);

    const isFirstAccount = (await db.Account.count()) === 0;
    account.role = isFirstAccount ? Role.Admin : Role.User;
    account.verificationToken = randomTokenString();

    account.passwordHash = await hash(params.password);

    await account.save();
    
    await sendVerificationEmail(account, origin);
  }

I'm not sure where to find the id.

Upvotes: 0

Views: 1654

Answers (1)

CapitanFindus
CapitanFindus

Reputation: 1526

based on your updated code your .register function is actually returning nothing. What you should do is update that function making it return the new created ID, or the already existing ID (if you need it).

accountService.register(req.body, req.get('origin'))
    .then(() => res.json(account.id));

This part of code you already tested doesn't work because of account missing inside the .then promise resolution. Also, as your method does not return anything, you won't be able to access anything inside the .then(() => {}) callback.

You could try updating the register function as following

async function register(params, origin) {
  const existingAccount = await db.Account.findOne({
      where: { email: params.email }
  });
  if (existingAccount) {
    await sendAlreadyRegisteredEmail(params.email, origin);
    return existingAccount.id;
  }

  const isFirstAccount = (await db.Account.count()) === 0;

  const accountParams = {
    ...params,
    role: isFirstAccount ? Role.Admin : Role.User,
    verificationToken: randomTokenString(),
    passwordHash: await hash(params.password)
  }
  
  const account = await db.Account.create(
    accountParams, { isNewRecord: true }
  );

  await sendVerificationEmail(account, origin);
  
  return account.id;
}

And update your API handler as following

accountService.register(req.body, req.get('origin'))
    .then((id) => res.json({id}))

Please note that if params.password is present, you are currently saving Account password both hashed and cleartext, which should be avoided

Upvotes: 1

Related Questions