zhlajiex's picture
Production Fix: Resolve fs ReferenceError in Multer, fix profile auth failure, and optimize controller lookups
5db933c
const { db } = require('../db');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
class User {
constructor(userData) {
Object.assign(this, userData);
this.id = userData._id; // Alias _id to id
}
static findOne(query) {
const chain = {
select: function(fields) {
return this;
},
then: function(resolve, reject) {
return new Promise((res, rej) => {
db.users.findOne(query, (err, doc) => {
if (err) rej(err);
else res(doc ? new User(doc) : null);
});
}).then(resolve, reject);
},
catch: function(reject) {
return this.then(null, reject);
}
};
return chain;
}
static async findById(id) {
return new Promise((resolve, reject) => {
db.users.findOne({ _id: id }, (err, doc) => {
if (err) reject(err);
else resolve(doc ? new User(doc) : null);
});
});
}
static async create(userData) {
const salt = await bcrypt.genSalt(10);
if (userData.password) {
userData.password = await bcrypt.hash(userData.password, salt);
}
userData.usage = userData.usage || { requestsToday: 0, lastRequestDate: new Date() };
userData.createdAt = userData.createdAt || new Date();
userData.role = userData.role || 'user';
const owners = ['johanvoncd7@gmail.com', 'codexai@mightysmp.online'];
if (owners.includes(userData.email)) {
userData.role = 'owner';
}
return new Promise((resolve, reject) => {
db.users.insert(userData, (err, newDoc) => {
if (err) reject(err);
else resolve(new User(newDoc));
});
});
}
static async findByIdAndUpdate(id, update) {
return new Promise((resolve, reject) => {
db.users.update({ _id: id }, { $set: update }, { returnUpdatedDocs: true }, (err, numReplaced, affectedDoc) => {
if (err) reject(err);
else resolve(affectedDoc ? new User(affectedDoc) : null);
});
});
}
async matchPassword(enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
}
getSignedJwtToken() {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE
});
}
getResetPasswordToken() {
const resetToken = crypto.randomBytes(20).toString('hex');
this.resetPasswordToken = crypto.createHash('sha256').update(resetToken).digest('hex');
this.resetPasswordExpire = Date.now() + 10 * 60 * 1000;
return resetToken;
}
async save() {
return new Promise((resolve, reject) => {
const data = { ...this };
const id = data._id;
delete data._id;
db.users.update({ _id: id }, { $set: data }, { upsert: true }, (err) => {
if (err) reject(err);
else resolve(this);
});
});
}
}
module.exports = User;