const database = require('./../database'); const passport = require('passport'); const localStrategy = require('passport-local').Strategy; const bcrypt = require('bcrypt'); class User { constructor(id, email, isAdmin, name) { this.id = id; this.email = email; this.isAdmin = isAdmin; this.name = name; } } async function checkForAdminAccount() { const adminUsersQuery = `SELECT * FROM accounts.users WHERE admin = true;`; const adminUsers = await database.executeQuery(adminUsersQuery); if(adminUsers.length == 0) { const passwordHash = await generateHash('admin'); const createTempAdminQuery = `INSERT INTO accounts.users(email, password, admin) VALUES('admin@example.com', $1, true);`; database.executeQuery(createTempAdminQuery, [passwordHash]); console.log("Created temp admin account 'admin@example.com' with password 'admin'."); } } database.initializationStatus.then(() => checkForAdminAccount()); passport.use(new localStrategy({ usernameField: 'email', passwordField: 'password'}, (username, password, cb) => { query = `SELECT user_id, email, password, admin FROM accounts.users WHERE email = $1`; database.executeQuery(query, [username]) .then(result => { if(result.length > 0) { const first = result[0]; const matches = bcrypt.compareSync(password, first[2]); if(matches) { return cb(null, { id: first[0], email: first[1], admin: first[3] }) } else { return cb(null, false) } } else { return cb(null, false) } }); })); passport.serializeUser((user, done) => { done(null, user.id) }) passport.deserializeUser((id, cb) => { query = `SELECT user_id, email, admin FROM accounts.users WHERE user_id = $1`; database.executeQuery(query, [parseInt(id, 10)]) .then(result => { cb(null, result[0]); }); }); async function generateHash(password) { const salt = bcrypt.genSaltSync(); return bcrypt.hashSync(password, salt); } async function create(email, password, isAdmin, name) { const hash = await generateHash(password); const query = `INSERT INTO accounts.users(email, password, admin, full_name) VALUES($1, $2, $3, $4)`; await database.executeQuery(query, [email, hash, isAdmin, name]); } async function edit(id, email, password, isAdmin, name) { if(password) { const hash = await generateHash(password); const query = `UPDATE accounts.users SET email = $2, password = $3, admin = $4, full_name = $5 WHERE user_id = $1;`; await database.executeQuery(query, [id, email, hash, isAdmin, name]); } else { const query = `UPDATE accounts.users SET email = $2, admin = $3, full_name = $4 WHERE user_id = $1;`; await database.executeQuery(query, [id, email, isAdmin, name]); } return new User(id, email, isAdmin, name); } async function remove(id) { const query = `DELETE FROM accounts.users WHERE user_id = $1 RETURNING email, admin, full_name;`; const row = (await database.executeQuery(query, [id]))[0]; return new User(id, row[0], row[1], row[2]); } async function retrieveAll() { const query = `SELECT user_id, email, admin, full_name FROM accounts.users ORDER BY full_name;`; const table = await database.executeQuery(query); const accountsList = []; table.forEach((row) => { accountsList.push(new User(row[0], row[1], row[2], row[3])); }); return accountsList; } async function getFromID(id) { const query = `SELECT user_id, email, admin, full_name FROM accounts.users WHERE user_id = $1;`; const row = (await database.executeQuery(query, [id]))[0]; return new User(id, row[1], row[2], row[3]); } exports.create = create; exports.edit = edit; exports.remove = remove; exports.retrieveAll = retrieveAll; exports.getFromID = getFromID; exports.passport = passport;