All files / server/api/auth auth.api.js

100% Statements 24/24
100% Branches 8/8
100% Functions 3/3
100% Lines 24/24
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          1x 1x   1x 1x 1x 1x 1x 1x     1x   1x                   1x   7x     5x 5x 5x 2x       3x 3x 1x     2x 2x     2x                 7x 7x                                
/**
 * Authentication API.
 *
 * @module server/api/auth
 */
const _ = require('lodash');
const moment = require('moment');
 
const config = require('../../../config');
const User = require('../../models/user');
const usersPolicy = require('../users/users.policy');
const { route } = require('../utils/api');
const errors = require('../utils/errors');
const { validateRequestBody } = require('../utils/validation');
 
// API resource name (used in some API errors).
exports.resourceName = 'auth';
 
const logger = config.logger(`api:${exports.resourceName}`);
 
/**
 * **POST /api/auth**
 *
 * Creates a new, short-lived (2 weeks) authentication token for a user.
 * The correct e-mail and password must be provided.
 *
 * @function
 */
exports.authenticate = route(async function(req, res) {
 
  await validateAuthentication(req);
 
  // Load the user by e-mail.
  const email = _.get(req, 'body.email', '_').toString();
  const user = await new User({ email: email.toLowerCase() }).fetch();
  if (!user || !user.isActive()) {
    throw errors.unauthorized('auth.invalidUser', 'This user account does not exist or is inactive.');
  }
 
  // Check the password.
  const password = req.body.password;
  if (!_.isString(password) || !user.hasPassword(password)) {
    throw errors.unauthorized('auth.invalidCredentials', 'The password is invalid.');
  }
 
  req.currentUser = user;
  logger.info(`User ${user.get('api_id')} has logged in`);
 
  // Return a new JWT and the user.
  res.status(201).json({
    token: user.generateJwt({
      exp: moment().add(2, 'weeks').unix()
    }),
    user: usersPolicy.serialize(req, user)
  });
});
 
function validateAuthentication(req) {
  return validateRequestBody(req, function() {
    return this.parallel(
      this.validate(
        this.json('/email'),
        this.required(),
        this.type('string'),
        this.email()
      ),
      this.validate(
        this.json('/password'),
        this.required(),
        this.type('string'),
        this.notBlank()
      )
    );
  });
}