UNPKG

@ideal-photography/shared

Version:

Shared GraphQL (Apollo Server v5) and Mongoose logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, and audit logs.

75 lines (64 loc) 2.29 kB
import mongoose from 'mongoose'; import bcrypt from 'bcryptjs'; const adminSchema = new mongoose.Schema({ username: { type: String, required: [true, 'Username is required'], unique: true, trim: true, minlength: [3, 'Username must be at least 3 characters'] }, password: { type: String, required: [true, 'Password is required'], minlength: [6, 'Password must be at least 6 characters'] }, role: { type: String, enum: ['admin', 'manager', 'super_admin'], default: 'admin' }, permissions: [{ type: String }], isActive: { type: Boolean, default: true }, isVerified: { type: Boolean, default: false }, verifiedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'Admin' }, verifiedAt: { type: Date }, loginAttempts: { type: Number, default: 0 }, lockUntil: { type: Date }, lastLogin: { type: Date }, createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'Admin' } }, { timestamps: true }); adminSchema.virtual('isLocked').get(function () { return !!(this.lockUntil && this.lockUntil > Date.now()); }); adminSchema.index({ username: 1 }, { unique: true }); adminSchema.index({ role: 1 }); adminSchema.pre('save', async function (next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 12); next(); }); adminSchema.methods.comparePassword = function (candidatePassword) { return bcrypt.compare(candidatePassword, this.password); }; adminSchema.methods.incLoginAttempts = function () { if (this.lockUntil && this.lockUntil < Date.now()) { return this.updateOne({ $unset: { lockUntil: 1 }, $set: { loginAttempts: 1 } }); } const updates = { $inc: { loginAttempts: 1 } }; if (this.loginAttempts + 1 >= 5 && !this.isLocked) { updates.$set = { lockUntil: Date.now() + 2 * 60 * 60 * 1000 }; } return this.updateOne(updates); }; adminSchema.methods.resetLoginAttempts = function () { return this.updateOne({ $unset: { loginAttempts: 1, lockUntil: 1 } }); }; export default mongoose.model('Admin', adminSchema);