All files / Zapcard_API/services auth.service.js

100% Statements 29/29
100% Branches 8/8
100% Functions 7/7
100% Lines 23/23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88                    1x 1x   1x 1x 1x                     3x 3x 2x 2x 1x     1x                             13x 13x 13x 13x 10x 10x       10x   3x                             2x 2x 1x           1x          
/**
 *  @fileOverview A service that handles login and authentication on each request.
 *
 *  @author       Ralfs Lagzda
 *
 *  @requires     NPM:mongoose
 *  @requires     NPM:jsonwebtoken
 *  @requires     ../models/user
 *  @requires     ../config
 */
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
 
mongoose.Promise = global.Promise;
const User = require('../models/user');
const config = require('../config');
 
/**
 * Authenticates a user based on the signed JWT token
 *
 * @memberOf AuthService
 * @function authenticate
 * @param {String} token - The signed user JWT token string
 * @returns {Promise<User>} Promise that eventually authenticates
 * and resolves the user or fails
 */
const authenticate = token => new Promise(async (resolve, reject) => {
  if (token) {
    jwt.verify(token, config.secretKey, (err, decode) => {
      if (err) reject(Error({ message: 'Invalid token' }));
      else resolve(decode.user);
    });
  } else {
    reject(Error({ message: 'No token' }));
  }
});
 
/**
 * Login a user based on the credentials
 *
 * @memberOf AuthService
 * @function login
 * @param {Object} credentials - The user credential object containing username and password
 * @param {string} credentials.username - The username.
 * @param {string} credentials.password - The password.
 * @returns {Promise<User>} Promise that eventually authenticates
 * and resolves the user with JWT or fails
 */
const login = credentials => new Promise(async (resolve, reject) => {
  try {
    const user = await User.findOne({ username: credentials.username });
    if (!await user.verifyPassword(credentials.password)) throw (Error('Invalid login'));
    user.password = undefined;
    const token = jwt.sign({
      expiresIn: 60 * 60 * 60 * 3, // expires in 3 hours
      user,
    }, config.secretKey);
    resolve({ token, user });
  } catch (err) {
    reject(err);
  }
});
 
/**
 * Authorizes access to a user or resource owned by a user
 *
 * @memberOf AuthService
 * @function authorize
 * @param {Object} authenticatedUser - The user which is currently authenticated
 * @param {string} authenticatedUser.id - The id of the user.
 * @param {String} userId - The user id in the path to access a resource
 * @returns {Promise<Boolean>} Promise that eventually authorizes the user
 * and resolves a boolean or fails
 */
const authorize = (authenticatedUser, userId) => new Promise((resolve, reject) => {
  if (authenticatedUser.id === userId) resolve();
  else reject(Error({ message: 'Not authorized' }));
});
/**
 * A service that handles login and authentication on each request
 * @namespace AuthService
 */
module.exports = {
  authenticate,
  authorize,
  login,
};