Source: user.service.js

/**
 *  @fileOverview A service that handles CRUD operations on users and picture uploads.
 *
 *  @author       Ralfs Lagzda
 *
 *  @requires     NPM:fs
 *  @requires     NPM:mkdirp
 *  @requires     NPM:checksum
 *  @requires     NPM:path
 *  @requires     ../models/user
 */

const fs = require('fs');
const mkdirp = require('mkdirp');
const checksum = require('checksum');
const path = require('path');
const User = require('../models/user');

/**
 * List all users
 *
 * @memberOf UserService
 * @function list
 * @returns {Promise<Card[]>} Promise that eventually resolves an array of users or throws error
 */
const list = () => new Promise(async (resolve, reject) => {
  try {
    resolve(await User.find({}));
  } catch (err) {
    reject(err);
  }
});
/**
 * Create a user
 *
 * @memberOf UserService
 * @function create
 * @param {Object} user the user object to create
 * @returns {Promise<User>} Promise that eventually creates and resolves a user or throws error
 */
const create = user => new Promise(async (resolve, reject) => {
  try {
    resolve(await new User(user).save());
  } catch (err) {
    reject(err);
  }
});
/**
 * Retrieves a single user by ID
 *
 * @memberOf UserService
 * @function read
 * @param {String} userId the ID of the user
 * @returns {Promise<User>} Promise that eventually resolves a user or throws error
 */
const read = userId => new Promise(async (resolve, reject) => {
  try {
    const user = await User.findById(userId);
    resolve(user);
  } catch (err) {
    reject(err);
  }
});
/**
 * Updates a single user
 *
 * @memberOf UserService
 * @function update
 * @param {String} userId the ID of the user
 * @param {Object} body key/value pairs of the fields that should be changed
 * @returns {Promise<User>} Promise that eventually updates and resolves a user or throws error
 */
const update = (userId, body) => new Promise(async (resolve, reject) => {
  try {
    resolve(await Object.assign(await User.findById(userId), body).save());
  } catch (err) {
    reject(err);
  }
});
/**
 * Deletes a single user
 *
 * @memberOf UserService
 * @function del
 * @param {String} userId the ID of the user
 * @returns {Promise} Promise that eventually deletes a user or throws error
 */
const del = userId => new Promise(async (resolve, reject) => {
  try {
    await User.remove({ _id: userId });
    resolve();
  } catch (err) {
    reject(err);
  }
});
/**
 * Removes sensitive information from the user object
 *
 * @memberOf UserService
 * @function stripSensitiveInformation
 * @param {Object} user the user object to be stripped
 * @returns {Object} the stripped user object
 */
const stripSensitiveInformation = (user) => {
  const publicUser = user;
  delete publicUser.password;
  return publicUser;
};
/**
 * Retrieve the profile picture for the user
 *
 * @memberOf UserService
 * @function getProfilePicture
 * @param {String} userId the userId folder path where to look for the picture
 * @returns {Buffer} the profile picture
 */
const getProfilePicture = userId => new Promise(async (resolve, reject) => {
  fs.readFile(path.resolve(`./uploads/${userId}/image.png`), (err, data) => {
    if (err) reject(err);
    else resolve(data);
  });
});
/**
 * Upload a picture for the user
 *
 * @memberOf UserService
 * @function modifyProfilePicture
 * @param {Object} user the user to which picture needs to be added
 * @param {Object} files the userId folder path where to look for the picture
 * @param {String} files.path the path where the temporary picture is currently stored
 * @returns {Buffer} the profile picture
 */
const modifyProfilePicture = (user, files) => new Promise(async (resolve, reject) => {
  try {
    if (!files.path) reject(Error('Path to file was not provided'));
    else {
      const oldPath = files.path;
      const newPath = path.resolve(`./uploads/${user.id}`);
      mkdirp(newPath, async () => {
        const readStream = fs.createReadStream(oldPath);
        readStream.once('error', (err) => {
          reject(err);
        });
        readStream.once('end', () => {
          checksum.file(`${newPath}/image.png`, async (err, sum) => {
            await Object.assign(user, { profilePicture: sum }).save();
            resolve(sum);
          });
        });
        readStream.pipe(fs.createWriteStream(`${newPath}/image.png`));
      });
    }
  } catch (err) {
    reject(err);
  }
});
/**
 * A service that handles CRUD operations on users and picture uploads.
 * @namespace UserService
 */
module.exports = {
  list,
  create,
  read,
  update,
  del,
  stripSensitiveInformation,
  modifyProfilePicture,
  getProfilePicture,
};