const mongoose = require('mongoose'); const validator = require('validator'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const schema = new mongoose.Schema({ name: { type: String, required: true, maxlength: 100, }, email: { type: String, lowercase: true, unique: true, required: true, validate(value) { if (!validator.isEmail(value)) { throw new Error('Invalid email format'); } } }, password: { type: String, required: true, minlength: 7, trim: true, }, tokens: [{ token: { type: String, required: true } }] }, { timestamps: true }); schema.pre('save', async function (next) { const user = this; if (user.isModified('password')) { user.password = await bcrypt.hash(user.password, 8); } next(); }); schema.statics.findByCredentials = async (email, password) => { const user = await model.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; }; schema.methods.generateAuthToken = async function () { const user = this; const token = jwt.sign({ _id: user._id.toString() }, process.env.JWT_SECRET); user.tokens = user.tokens.concat({ token }); await user.save(); return token; }; schema.methods.toJSON = function () { const user = this; const publicUserData = user.toObject(); delete publicUserData.password; delete publicUserData.tokens; return publicUserData }; const model = mongoose.model( 'Users', schema ); module.exports = { schema, model };