import { hashPassword, verifyPassword, } from '../utils/helpers/hashPasswordHelpers'; import { Schema, model, Model, models } from 'mongoose'; import { IUser } from '../utils/interface/userInterface'; const validator = require('validator'); interface UserModel extends Model { findByCredentials(username: string, password: string): object; } const UserSchema = new Schema({ fullName: { type: String, required: [true, 'Please provide a name.'], maxlength: [60, 'Name cannot be more than 60 characters'], trim: true, }, username: { type: String, required: [true, 'Please provide a name.'], maxlength: [60, 'Name cannot be more than 60 characters'], trim: true, unique: true, }, email: { type: String, unique: true, required: true, trim: true, lowercase: true, validate(value: string) { if (!validator.isEmail(value)) { throw new Error('Email is invalid'); } }, }, password: { type: String, required: true, minlength: 7, trim: true, validate(value: string) { if (value.toLowerCase().includes('password')) { throw new Error('Password cannot contain "password"'); } }, }, }); UserSchema.static( 'findByCredentials', async function findByCredentials(username: string, password: string) { const user = await User.findOne({ username }); if (!user) { throw new Error('Unable to login'); } const isMatch = await verifyPassword(password, user.password); if (!isMatch) { throw new Error('Unable to login'); } const userData = { fullName: user.fullName, email: user.email, username: user.username, }; return userData; } ); UserSchema.pre('save', async function (next) { const user = this; if (user.isModified('password')) { user.password = await hashPassword(user.password); } next(); }); const User = models.User || model('User', UserSchema); module.exports = User;