Spaces:
Running
Running
File size: 1,425 Bytes
1e480b5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema(
{
name: { type: String, required: true, trim: true },
username: { type: String, required: true, unique: true, lowercase: true, trim: true },
password: { type: String, required: true, minlength: 6 },
role: { type: String, enum: ['owner', 'cashier'], default: 'cashier' },
active: { type: Boolean, default: true },
adminPin: { type: String, default: null }, // 4-digit PIN for owner, used for void/refund
},
{ timestamps: true }
);
// Hash password and adminPin before save (single hook — async, no `next`)
userSchema.pre('save', async function () {
if (this.isModified('password') && this.password) {
this.password = await bcrypt.hash(this.password, 12);
}
if (this.isModified('adminPin') && this.adminPin) {
this.adminPin = await bcrypt.hash(this.adminPin, 12);
}
});
userSchema.methods.matchPassword = function (entered) {
return bcrypt.compare(entered, this.password);
};
userSchema.methods.matchPin = function (entered) {
if (!this.adminPin) return Promise.resolve(false);
return bcrypt.compare(entered, this.adminPin);
};
// Never return password in JSON responses
userSchema.set('toJSON', {
transform: (_, obj) => {
delete obj.password;
delete obj.adminPin;
return obj;
},
});
module.exports = mongoose.model('User', userSchema);
|