UNPKG

get-express-starter

Version:

Get production ready express boilerplate with a single command

146 lines (130 loc) 3.94 kB
const jwt = require('jsonwebtoken'); const moment = require('moment'); const httpStatus = require('http-status'); const env = require('../config/env'); const userService = require('./user.service'); const { Token } = require('../models'); const ApiError = require('../utils/ApiError'); const { tokenTypes } = require('../config/tokens'); /** * Generate token * @param {ObjectId} userId * @param {Moment} expires * @param {string} type * @param {string} [secret] * @returns {string} */ const generateToken = (userId, expires, type, secret = env.jwt.secret) => { const payload = { sub: userId, iat: moment().unix(), exp: expires.unix(), type, }; return jwt.sign(payload, secret); }; /** * Save a token * @param {string} token * @param {ObjectId} userId * @param {Moment} expires * @param {string} type * @param {boolean} [blacklisted] * @returns {Promise<Token>} */ const saveToken = async (token, userId, expires, type, blacklisted = false) => { const tokenDoc = await Token.create({ token, user: userId, expires: expires.toDate(), type, blacklisted, }); return tokenDoc; }; /** * Verify token and return token doc (or throw an error if it is not valid) * @param {string} token * @param {string} type * @returns {Promise<Token>} */ const verifyToken = async (token, type) => { const payload = jwt.verify(token, env.jwt.secret); const tokenDoc = await Token.findOne({ token, type, user: payload.sub, blacklisted: false }); if (!tokenDoc) { throw new Error('Token not found'); } return tokenDoc; }; /** * Generate auth tokens * @param {User} user * @returns {Promise<Object>} */ const generateAuthTokens = async (user) => { const accessTokenExpires = moment().add(env.jwt.accessExpirationMinutes, 'minutes'); const accessToken = generateToken(user.id, accessTokenExpires, tokenTypes.ACCESS); const refreshTokenExpires = moment().add(env.jwt.refreshExpirationDays, 'days'); const refreshToken = generateToken(user.id, refreshTokenExpires, tokenTypes.REFRESH); await saveToken(refreshToken, user.id, refreshTokenExpires, tokenTypes.REFRESH); return { access: { token: accessToken, expires: accessTokenExpires.toDate(), }, refresh: { token: refreshToken, expires: refreshTokenExpires.toDate(), }, }; }; /** * Generate reset password token * @param {string} email * @returns {Promise<string>} */ const generateResetPasswordToken = async (email) => { const user = await userService.getUserByEmail(email); if (!user) { throw new ApiError(httpStatus.NOT_FOUND, 'No users found with this email'); } const expires = moment().add(env.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = generateToken(user.id, expires, tokenTypes.RESET_PASSWORD); await saveToken(resetPasswordToken, user.id, expires, tokenTypes.RESET_PASSWORD); return resetPasswordToken; }; /** * Generate verify email token * @param {User} user * @returns {Promise<string>} */ const generateVerifyEmailToken = async (user) => { const expires = moment().add(env.jwt.verifyEmailExpirationMinutes, 'minutes'); const verifyEmailToken = generateToken(user.id, expires, tokenTypes.VERIFY_EMAIL); await saveToken(verifyEmailToken, user.id, expires, tokenTypes.VERIFY_EMAIL); return verifyEmailToken; }; const getTheToken = async (token) => { const result = await Token.findOne({ token }); if (!result) { throw new ApiError(httpStatus.NOT_FOUND, 'Token not found'); } return result; }; const deleteTheToken = async (token) => { const result = await Token.deleteOne({ token }); if (!result) { throw new ApiError(httpStatus.NOT_FOUND, 'Token not found'); } return result; }; module.exports = { generateToken, saveToken, verifyToken, generateAuthTokens, generateResetPasswordToken, generateVerifyEmailToken, getTheToken, deleteTheToken, };