import mongoose from 'mongoose'; import bcrypt from 'bcryptjs'; const UserSchema = new mongoose.Schema({ email: { type: String, required: [true, 'Email is required'], unique: true, trim: true, lowercase: true, match: [/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/, 'Please provide a valid email'] }, name: { type: String, required: [true, 'Name is required'], trim: true, minlength: [2, 'Name must be at least 2 characters'] }, hashed_password: { type: String, required: [true, 'Password is required'] }, role: { type: String, enum: { values: ['admin', 'doctor', 'patient'], message: '{VALUE} is not a valid role' }, default: 'doctor' }, is_active: { type: Boolean, default: true }, specialization: { type: String, trim: true }, phone: { type: String, trim: true }, address: { type: String, trim: true } }, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }); // Index for faster queries UserSchema.index({ role: 1 }); UserSchema.index({ is_active: 1 }); // Hash password before saving UserSchema.pre('save', async function() { // Only hash the password if it has been modified (or is new) if (!this.isModified('hashed_password')) return; // Check if the password is already hashed (bcrypt hashes start with $2) if (this.hashed_password.startsWith('$2')) return; const salt = await bcrypt.genSalt(10); this.hashed_password = await bcrypt.hash(this.hashed_password, salt); }); // Method to check password UserSchema.methods.comparePassword = async function(candidatePassword) { return bcrypt.compare(candidatePassword, this.hashed_password); }; // Method to convert to response object (exclude sensitive data) UserSchema.methods.toResponse = function() { return { id: this._id.toString(), email: this.email, name: this.name, role: this.role, is_active: this.is_active, specialization: this.specialization, phone: this.phone, created_at: this.created_at }; }; // Static method to find by email UserSchema.statics.findByEmail = function(email) { return this.findOne({ email: email.toLowerCase() }); }; // Static method to find active doctors UserSchema.statics.findActiveDoctors = function() { return this.find({ role: 'doctor', is_active: true }); }; // Static method to find active admins UserSchema.statics.findActiveAdmins = function() { return this.find({ role: 'admin', is_active: true }); }; const User = mongoose.model('User', UserSchema); export default User;