const map = require('lodash/map'); const AuthTokens = require('../authtokens'); const bcrypt = require('bcrypt'); class User { constructor(values) { var self = this; self.id = values.id || values._id || null; self.username = values.username || null; self.name = values.name || null; self.password = values.password || null; self.email = values.email || null; self.auth = values.auth || []; if (values.hasOwnProperty('active')) self.active = (values.active === true); else self.active = true; self.created = values.created || new Date(); self.createdByUserId = values.createdByUserId || null; } hasAuth(token) { var self = this; return self.auth.includes(token); } } class UserRepository { constructor(store) { var self = this; self.store = store; } init() { var self = this; return new Promise((resolve, reject) => { // Initialize database if empty self.store.count({}, (err, count) => { if (err) { reject(err); return; } if (count == 0) { self.insert(new User({ username: 'admin', name: 'Administrator', password: 'changeme', auth: AuthTokens.all })) .then(() => { resolve() }) .catch((e) => { reject(e); }); } else resolve(); }); }); } getLoginUser(username, password) { var self = this; return new Promise((resolve, reject) => { self.store.findOne({ $or: [{ username: username }, { email: username }], active: true }, (err, doc) => { if (err) { reject(err); return; } if (doc == null) { resolve(null); return; } bcrypt.compare(password, doc.hashedPassword, (err, res) => { if (err) reject(err) else resolve(res ? new User(doc) : null); }); }); }); } list() { var self = this; return new Promise((resolve, reject) => { self.store.find({}, (err, docs) => { if (err) { reject(err); return; } resolve(map(docs, (doc) => new User(doc))); }); }); } get(userId) { var self = this; return new Promise((resolve, reject) => { self.store.findOne({ _id: userId }, (err, doc) => { if (err) { reject(err); return; } resolve(doc !== null ? new User(doc) : null); }); }); } insert(user) { var self = this; return new Promise((resolve, reject) => { bcrypt.hash(user.password, 10, function(err, hash) { if (err) { reject(err); return; } self.store.insert({ username: user.username, name: user.name, email: user.email, hashedPassword: hash, created: user.created || new Date(), createdByUserId: user.createdByUserId, active: user.active, auth: user.auth || [] }, (err, dbUser) => { if (err) { reject(err); return; } resolve(dbUser._id); }); }); }); } update(user) { var self = this; return new Promise((resolve, reject) => { let doUpdate = (newPassword) => { let updateObject = { username: user.username, name: user.name, email: user.email, active: user.active, auth: user.auth }; if (newPassword !== null) updateObject.hashedPassword = newPassword; self.store.update({ _id: user.id }, { $set: updateObject }, (err, numAffected) => { if (err) { reject(err); return; } if (numAffected == 0) { reject(); } resolve(); }); }; if (user.password) { bcrypt.hash(user.password, 10, function(err, hash) { if (err) { reject(err); return; } doUpdate(hash); }); } else doUpdate(null); }); } delete(userId) { var self = this; return new Promise((resolve, reject) => { self.store.remove({ _id: userId }, (err, numRemoved) => { if (err) { reject(err); return; } resolve(); }); }); } getNames() { var self = this; return new Promise((resolve, reject) => { self.store.find({}, (err, docs) => { if (err) { reject(err); return; } var userNames = {}; docs.forEach((dbUser) => { userNames[dbUser._id] = dbUser.name }); resolve(userNames); }); }); } } module.exports = { User, UserRepository }