const mongoose = require('mongoose') const bcrypt = require('bcryptjs') const { randomBytes } = require('crypto') const userSchema = new mongoose.Schema({ email: { type: String, trim: true, lowercase: true, unique: true, required: true, min: 4, max: 255, validate: { validator: v => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v), message: "Please enter a valid email" }, }, password: { type: String, required: true, max: 1024, min: 6, }, refresh: { type: String, required: true, max: 1024, min: 6, }, verify: { type: String, default: randomBytes(3).toString('hex'), }, role: { type: String, max: 16, min: 3, default: 'user', }, date: { type: Date, default: Date.now, }, }) userSchema.statics.checkRefreshToken = async (email, refresh) => { const user = await User.findOne({ email }) if (!user) { throw new Error('User not found') } const isMatch = await bcrypt.compare(refresh, user.refresh) if (!isMatch) { throw new Error('Wrong refresh token') } return user } userSchema.statics.findByCredentials = async (email, password) => { const user = await User.findOne({ email }) if (!user) { throw new Error('Unable to login') } const isMatch = await bcrypt.compare(password, user.password) if (!isMatch) { throw new Error('Unable to login') } return user } userSchema.statics.newRefreshToken = async (user) => { const newRefreshToken = randomBytes(32).toString('hex') user.refresh = newRefreshToken try { await user.save() return newRefreshToken } catch(err) { return '' } } userSchema.pre('save', async function(next){ const user = this if (user.isModified('password')) { user.password = await bcrypt.hash(user.password, 8) } if (user.isModified('refresh')) { user.refresh = await bcrypt.hash(user.refresh, 8) } next() }) const User = mongoose.model('User', userSchema) module.exports = User