@kapvm/create-express-app
Version:
A CLI tool to scaffold an Express.js boilerplate project
133 lines (112 loc) • 3.25 kB
JavaScript
const crypto = require('crypto');
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
//modeling the database collection
const userSchema = new mongoose.Schema({
name: {
type: String,
require: [true, 'User must enter name'],
},
email: {
type: String,
required: [true, 'User must enter email'],
unique: [true, 'Email already in use'],
lowercase: true,
validate: [validator.isEmail, 'Please enter a valid email'],
},
photo: {
type: String,
default: 'default.jpg',
},
password: {
type: String,
required: [true, 'User must enter password'],
minlength: 8,
maxlength: 64,
select: false,
},
passwordConfirm: {
type: String,
required: [true, 'User must enter password'],
minlength: 8,
maxlength: 64,
validate: {
validator: function (val) {
return this.password === val;
},
message: 'Password and Password Confirm must be same',
},
},
passwordChangedAt: {
type: Date,
},
passwordResetToken: String,
passwordResetExpires: Date,
active: {
type: Boolean,
default: true,
select: false,
},
deletedAt: {
type: Date,
},
createdAt: {
type: Date,
default: Date.now(),
},
});
//LABEL
// HOOKS
//=> Password Encryption logic
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 12);
this.passwordConfirm = undefined;
});
//=> set password changed at property dynamically
userSchema.pre('save', function (next) {
if (!this.isModified('password') || this.isNew) return next();
this.passwordChangedAt = Date.now() - 1000;
next();
});
//=> filter to get only active users
userSchema.pre(/^find/g, function (next) {
this.find({ active: { $ne: false } });
next();
});
//LABEL
// Methods
//=> check if user entered password is correct or not (return false if not same)
userSchema.methods.checkPassword = async function (
candidatePassword,
userPassword,
) {
//candidatePassword = password that is entered by user in forms (from req)
//userPassword = password that is stored in db (actual password)
//Use the 'bcrypt' package's compare method, which compares both strings even if either is encrypted
return await bcrypt.compare(candidatePassword, userPassword);
};
//=> method to check if password is changed after the token generated or not
userSchema.methods.isPasswordChangedAfter = function (JWTTokenTime) {
if (this.passwordChangedAt) {
const passwordChangedTime = parseInt(
this.passwordChangedAt.getTime() / 1000,
);
return JWTTokenTime < passwordChangedTime;
}
return false;
};
//=> getting the password reset token [simply generating and returning the token]
userSchema.methods.getPasswordResetToken = function () {
const resetToken = crypto.randomBytes(32).toString('hex');
this.passwordResetToken = crypto
.createHash('sha256')
.update(resetToken)
.digest('hex');
this.passwordResetExpires = Date.now() + 10 * 60 * 1000;
return resetToken;
};
//=> creating the collection
const User = mongoose.model('User', userSchema);
module.exports = User;