Spaces:
Runtime error
Runtime error
const mongoose = require('mongoose'); | |
const bcrypt = require('bcryptjs'); | |
const jwt = require('jsonwebtoken'); | |
const Joi = require('joi'); | |
const DebugControl = require('../utils/debug.js'); | |
function log({ title, parameters }) { | |
DebugControl.log.functionName(title); | |
DebugControl.log.parameters(parameters); | |
} | |
const Session = mongoose.Schema({ | |
refreshToken: { | |
type: String, | |
default: '', | |
}, | |
}); | |
const userSchema = mongoose.Schema( | |
{ | |
name: { | |
type: String, | |
}, | |
username: { | |
type: String, | |
lowercase: true, | |
required: [true, 'can\'t be blank'], | |
match: [/^[a-zA-Z0-9_-]+$/, 'is invalid'], | |
index: true, | |
}, | |
email: { | |
type: String, | |
required: [true, 'can\'t be blank'], | |
lowercase: true, | |
unique: true, | |
match: [/\S+@\S+\.\S+/, 'is invalid'], | |
index: true, | |
}, | |
emailVerified: { | |
type: Boolean, | |
required: true, | |
default: false, | |
}, | |
password: { | |
type: String, | |
trim: true, | |
minlength: 8, | |
maxlength: 128, | |
}, | |
avatar: { | |
type: String, | |
required: false, | |
}, | |
provider: { | |
type: String, | |
required: true, | |
default: 'local', | |
}, | |
role: { | |
type: String, | |
default: 'USER', | |
}, | |
googleId: { | |
type: String, | |
unique: true, | |
sparse: true, | |
}, | |
openidId: { | |
type: String, | |
unique: true, | |
sparse: true, | |
}, | |
githubId: { | |
type: String, | |
unique: true, | |
sparse: true, | |
}, | |
discordId: { | |
type: String, | |
unique: true, | |
sparse: true, | |
}, | |
plugins: { | |
type: Array, | |
default: [], | |
}, | |
refreshToken: { | |
type: [Session], | |
}, | |
}, | |
{ timestamps: true }, | |
); | |
//Remove refreshToken from the response | |
userSchema.set('toJSON', { | |
transform: function (_doc, ret) { | |
delete ret.refreshToken; | |
return ret; | |
}, | |
}); | |
userSchema.methods.toJSON = function () { | |
return { | |
id: this._id, | |
provider: this.provider, | |
email: this.email, | |
name: this.name, | |
username: this.username, | |
avatar: this.avatar, | |
role: this.role, | |
emailVerified: this.emailVerified, | |
plugins: this.plugins, | |
createdAt: this.createdAt, | |
updatedAt: this.updatedAt, | |
}; | |
}; | |
userSchema.methods.generateToken = function () { | |
const token = jwt.sign( | |
{ | |
id: this._id, | |
username: this.username, | |
provider: this.provider, | |
email: this.email, | |
}, | |
process.env.JWT_SECRET, | |
{ expiresIn: eval(process.env.SESSION_EXPIRY) }, | |
); | |
return token; | |
}; | |
userSchema.methods.generateRefreshToken = function () { | |
const refreshToken = jwt.sign( | |
{ | |
id: this._id, | |
username: this.username, | |
provider: this.provider, | |
email: this.email, | |
}, | |
process.env.JWT_REFRESH_SECRET, | |
{ expiresIn: eval(process.env.REFRESH_TOKEN_EXPIRY) }, | |
); | |
return refreshToken; | |
}; | |
userSchema.methods.comparePassword = function (candidatePassword, callback) { | |
bcrypt.compare(candidatePassword, this.password, (err, isMatch) => { | |
if (err) { | |
return callback(err); | |
} | |
callback(null, isMatch); | |
}); | |
}; | |
module.exports.hashPassword = async (password) => { | |
const hashedPassword = await new Promise((resolve, reject) => { | |
bcrypt.hash(password, 10, function (err, hash) { | |
if (err) { | |
reject(err); | |
} else { | |
resolve(hash); | |
} | |
}); | |
}); | |
return hashedPassword; | |
}; | |
module.exports.validateUser = (user) => { | |
log({ | |
title: 'Validate User', | |
parameters: [{ name: 'Validate User', value: user }], | |
}); | |
const schema = { | |
avatar: Joi.any(), | |
name: Joi.string().min(2).max(80).required(), | |
username: Joi.string() | |
.min(2) | |
.max(80) | |
.regex(/^[a-zA-Z0-9_-]+$/) | |
.required(), | |
password: Joi.string().min(8).max(128).allow('').allow(null), | |
}; | |
return schema.validate(user); | |
}; | |
const User = mongoose.model('User', userSchema); | |
module.exports = User; | |