/**
* @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,
};