src/models/user.js
// Import the neccesary modules.
import bcrypt from 'bcrypt-nodejs';
import jwt from 'jsonwebtoken';
import mongoose from 'mongoose';
/**
* The user schema used by mongoose.
* @type {Schema}
* @see http://mongoosejs.com/docs/guide.html
*/
const _userSchema = new mongoose.Schema({
_id: {
type: String,
required: true,
index: {
unique: true
}
},
firstname: {
type: String,
required: true
},
lastname: {
type: String,
required: true
},
email: {
type: String,
required: true, unique: true
},
username: {
type: String,
required: true, unique: true
},
password: {
type: String,
required: true
},
beers: [{
type: String,
ref: 'Beer'
}]
}, {
versionKey: false
});
/**
* Function executed before saving the user.
* @param {function} next - The next function for Express.
* @returns {void}
*/
function pre(next) {
const user = this;
if (!user.isModified('password')) return next();
bcrypt.genSalt(10, (err, salt) => {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, (err, hash) => {
if (err) return next(err);
user.password = hash;
return next();
});
});
}
/**
* Verify if a password is correct.
* @param {String} password - The password to verify.
* @param {function} callback - The function to return.
* @returns {function} - The callback function.
*/
function verifyPassword(password, callback) {
bcrypt.compare(password, this.password, (err, isMatch) => {
if (err) return callback(err);
return callback(null, isMatch);
});
}
/**
* Generate a JSON webtoken for a user.
* @returns {Object} - The generated webtoken.
*/
function generateJWT() {
const today = new Date();
const exp = new Date(today);
exp.setDate(today.getDate() + 60);
const { _id, username } = this;
return jwt.sign({
_id, username,
exp: parseInt(exp.getTime() / 1000, 10)
}, process.env.SECRET || 'SECRET');
}
/**
* Add a beer from the 'beers' array.
* @param {Sting} beer - The beer to add.
* @returns {Promise} - A promise to save the user.
*/
function addBeer(beer) {
this.beers.push(beer.name);
return this.save();
}
/**
* Remove a beer from the 'beers' array.
* @param {Sting} beer - The beer to remove.
* @returns {Promise} - A promise to save the user.
*/
function removeBeer(beer) {
const index = this.beers.indexOf(beer.name);
this.beers.splice(index, 1);
return this.save();
}
// Adding the functions to the user model.
_userSchema.pre('save', pre);
_userSchema.methods.verifyPassword = verifyPassword;
_userSchema.methods.generateJWT = generateJWT;
_userSchema.methods.addBeer = addBeer;
_userSchema.methods.removeBeer = removeBeer;
/**
* A model object for users.
* @type {User}
*/
export default mongoose.model('User', _userSchema);