create-bodhi-node-boilerplate
Version:
Create a Node.js project with basic folder structure and server setup
105 lines (95 loc) • 2.79 kB
JavaScript
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('../config/config');
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, 'Please provide a username'],
unique: true,
trim: true,
minlength: [3, 'Username must be at least 3 characters long'],
maxlength: [30, 'Username cannot be more than 30 characters'],
lowercase: true,
match: [
/^[a-zA-Z0-9_]+$/,
'Username can only contain letters, numbers, and underscores'
]
},
email: {
type: String,
required: [true, 'Please provide an email'],
unique: true,
lowercase: true,
trim: true,
match: [
/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/,
'Please provide a valid email'
]
},
password: {
type: String,
required: [true, 'Please provide a password'],
minlength: [6, 'Password must be at least 6 characters long'],
select: false
},
refreshTokenHash: {
type: String,
select: false
},
createdAt: {
type: Date,
default: Date.now
},
lastLogin: {
type: Date
}
}, {
timestamps: true
});
// Hash password before saving
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) {
next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
});
// Sign JWT access token
userSchema.methods.getSignedJwtToken = function() {
return jwt.sign(
{ id: this._id },
config.jwt.secret,
{ expiresIn: config.jwt.accessExpire }
);
};
// Sign refresh token
userSchema.methods.getRefreshToken = function() {
return jwt.sign(
{ id: this._id },
config.jwt.refreshSecret,
{ expiresIn: config.jwt.refreshExpire }
);
};
// Match password
userSchema.methods.matchPassword = async function(enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};
// Hash refresh token for storage
userSchema.methods.hashToken = async function(token) {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(token, salt);
};
// Verify refresh token
userSchema.methods.verifyRefreshToken = async function(token) {
if (!this.refreshTokenHash) return false;
return await bcrypt.compare(token, this.refreshTokenHash);
};
// Remove sensitive fields when converting to JSON
userSchema.methods.toJSON = function() {
const obj = this.toObject();
delete obj.password;
delete obj.refreshTokenHash;
return obj;
};
module.exports = mongoose.model('User', userSchema);