|
|
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; |
|
|
} |
|
|
|
|
|
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; |
|
|
|