'use strict'; const Util = require('util'); const Jwt = require('@hapi/jwt'); const Schmervice = require('@hapipal/schmervice'); const SecurePassword = require('secure-password'); module.exports = class UserService extends Schmervice.Service { constructor(...args) { super(...args) const pwd = new SecurePassword() this.pwd = { hash: Util.promisify(pwd.hash.bind(pwd)), verify: Util.promisify(pwd.verify.bind(pwd)) } } async findById(id, txn) { const { User } = this.server.models() return await User.query(txn).throwIfNotFound().findById(id) } async findByUsername(username, txn) { const { User } = this.server.models() return await User.query(txn).throwIfNotFound().first().where({ username }) } async signup({ password, ...userInfo }, txn) { const { User } = this.server.models() const { id } = await User.query(txn).insert(userInfo) await this.changePassword(id, password, txn) return id } async update(id, { password, ...userInfo }, txn) { const { User } = this.server.models() if (Object.keys(userInfo).length > 0) { await User.query(txn).throwIfNotFound().where({ id }).patch(userInfo) } if (password) { await this.changePassword(id, password, txn) } return id } async login({ email, password }, txn) { const { User } = this.server.models() const user = await User.query(txn) .throwIfNotFound() .first() .where({ user_email: email }) // Uncomment to run password check using SecurePassword // const passwordCheck = await this.pwd.verify(Buffer.from(password), user.password) // if (passwordCheck === SecurePassword.VALID_NEEDS_REHASH) { // await this.changePassword(user.id, password, txn) // } // else if (passwordCheck !== SecurePassword.VALID) { // throw User.createNotFoundError() // } return user } createToken(user) { const key = this.server.registrations['main-app-plugin'].options.jwtKey return Jwt.token.generate({ aud: 'urn:audience:test', iss: 'urn:issuer:test', email: user.user_email }, { key: key, algorithm: 'HS256' }, { ttlSec: 4 * 60 * 60 // 7 days }) } async changePassword(id, password, txn) { const { User } = this.server.models() await User.query(txn).throwIfNotFound().where({ id }).patch({ password: await this.pwd.hash(Buffer.from(password)) }) return id } }