Source: services/resetTokens/update.service.js

import { statusCodes } from '../../configs';
import { ResetToken } from '../../database';

/**
 * Find and update reset token record
 *
 * @memberof module:services/resetTokens
 * @param {Number} id Primary key to find.
 * @param {Object} resetTokenData JSON object of data to update.
 * @param {Boolean} [resetTokenData.isUsed] Has the token been used.
 * @returns {Object} JSON token object.
 * @throws Will throw an error if now primary key id or token data is passed in.
 * @throws Will throw an error if no resetToken is created
 * @example
 * import { resetTokens as resetTokensService } from '/src/services';
 * const id = 1;
 * const data = { isUsed: false }
 * const createdResetToken = await resetTokensService.updateOneByPk(id,data);
 */
const updateOneByPk = async (id, resetTokenData) => {
  try {
    // Check we have the required paramter
    if (!id || !resetTokenData) {
      const error = new Error('SERVICE ERROR: Insufficient parameters in reset token update request.');
      error.statusCode = statusCodes.INTERNAL_SERVER_ERROR;
      throw error;
    }

    // Find user to be updated
    const foundResetToken = await ResetToken.findOne({
      where: {
        id: id,
      },
    });

    // Check we have a reset token record
    if (!foundResetToken) {
      const error = new Error(`SERVICE ERROR: Reset token ${id} was not found to update.`);
      error.statusCode = statusCodes.INTERNAL_SERVER_ERROR;
      throw error;
    }

    // Update reset token information only if we have a value
    // False will not get in, so we need a deep equals
    if (resetTokenData.isUsed || resetTokenData.isUsed === false) {
      foundResetToken.isUsed = resetTokenData.isUsed;
    }

    // Save reset token instance to the database
    await foundResetToken.save();

    // Return the saved instance
    return foundResetToken;
  } catch (error) {
    throw error;
  }
};

/**
 * Set all token records for a given UserId as used.
 *
 * @memberof module:services/resetTokens
 * @param {String} UserId - UserId to set all token records as isUsed TRUE
 * @returns {Boolean} Return TRUE if updated or error
 * @throws Will throw an error if no UserId is passed in
 * @example
 * import { resetTokens as resetTokensService } from '/src/services';
 * const UserId = 1;
 * await resetTokensService.updateUsedByUserId(UserId);
 */
const updateUsedByUserId = async (UserId) => {
  try {
    if (!UserId) {
      const error = new Error('SERVICE ERROR: No UserId was provided to update reset tokens used.');
      // TODO think through status code to use in this authentication workflow
      error.statusCode = statusCodes.INTERNAL_SERVER_ERROR;
      throw error;
    }

    // Update all tokens for given email to isUsed:true
    await ResetToken.update(
      {
        isUsed: true,
      },
      {
        where: {
          UserId: UserId,
        },
      }
    );

    return true;
  } catch (error) {
    throw error;
  }
};

export { updateOneByPk, updateUsedByUserId };
export default { oneByPk: updateOneByPk, usedByUserId: updateUsedByUserId };