text: ﻿const config = require('config.json');
  const jwt = require('jsonwebtoken');
  const bcrypt = require('bcryptjs');
  const db = require('_helpers/db');
  const User = db.User;
  
  module.exports = {
      authenticate,
      getAll,
      getById,
      create,
      update,
      delete: _delete
  };
  
  async function authenticate({ email, password }) {
      const user = await User.findOne({ email });
      if (user && bcrypt.compareSync(password, user.password)) {
          const { hash, ...userWithoutHash } = user.toObject();
          const token = jwt.sign({ sub: user.id }, config.secret);
          return {
              ...userWithoutHash,
              token
          };
      }
  }
  
  async function getAll() {
      return await User.find().select('-hash');
  }
  
  async function getById(id) {
      return await User.findById(id).select('-hash');
  }
  
  async function create(userParam) {
      // validate
      if (await User.findOne({ email: userParam.email })) {
          throw 'Email "' + userParam.email + '" is already taken';
      }
  
      const user = new User(userParam);
  
      // hash password
      if (userParam.password) {
          user.hash = bcrypt.hashSync(userParam.password, 10);
      }
  
      // save user
      await user.save();
  }
  
  async function update(id, userParam) {
      const user = await User.findById(id);
  
      // validate
      if (!user) throw 'User not found';
      if (user.name !== userParam.name && await User.findOne({ name: userParam.name })) {
          throw 'Username "' + userParam.name + '" is already taken';
      }
  
      // hash password if it was entered
      if (userParam.password) {
          userParam.password = bcrypt.hashSync(userParam.password, 10);
      }
  
      // copy userParam properties to user
      Object.assign(user, userParam);
  
      await user.save();
  }
  
  async function _delete(id) {
      await User.findByIdAndRemove(id);
  }
  