Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict'
- const bcrypt = require('bcrypt')
- const jwt = require('jsonwebtoken')
- const Joi = require('joi')
- const credentialsSchema = require('../schema/credentials')
- module.exports = (database) => {
- const collectionName = process.env.DB_USERS_COLLECTION_NAME
- const secret = process.env.JWT_SECRET
- const saltRounds = Number(process.env.PASSWORD_SALT_ROUNDS)
- const collection = database.collection(collectionName)
- /**
- * Creates a new user, returns a promise which resolves into JWT token
- * @param {*} credentials an object with {username:String, password: String}
- */
- function create(credentials) {
- return new Promise((resolve, reject) => {
- const result = Joi.validate(credentials, credentialsSchema)
- if (result.error) {
- return reject(result.error)
- }
- try {
- const token = createUserInternal(collection, credentials, secret, saltRounds)
- return resolve(token)
- } catch (error) {
- return reject(error)
- }
- })
- }
- /**
- * Performs user login, returns a promise which resolves into JWT token, or throws an error
- * @param {*} credentials an object with {username:String, password: String}
- */
- function login(credentials) {
- return new Promise((resolve, reject) => {
- const result = Joi.validate(credentials, credentialsSchema)
- if (result.error) {
- return reject(result.error)
- }
- try {
- const token = loginInternal(collection, credentials, secret)
- return resolve(token)
- } catch (error) {
- return reject(error)
- }
- })
- }
- async function loginInternal(collection, credentials, secret) {
- const user = await collection.findOne({
- name: credentials.name
- })
- if (!user) {
- throw 'invalid user name'
- }
- const isPasswordOk = await bcrypt.compare(credentials.password, user.passwordHash)
- if (!isPasswordOk) {
- throw 'invalid password'
- }
- return sign(credentials, secret)
- }
- async function createUserInternal(collection, credentials, secret, saltRounds) {
- const hashedPassword = await bcrypt.hash(credentials.password, saltRounds)
- const user = {
- name: credentials.name,
- passwordHash: hashedPassword
- }
- await collection.insertOne(user)
- return sign(credentials, secret)
- }
- function sign(credentials, secret) {
- return jwt.sign({
- exp: Math.floor(Date.now() / 1000) + (60 * 60), // 1 hour from now
- data: {
- name: credentials.name
- }
- }, secret)
- }
- return Object.assign({}, {
- create,
- login
- })
- }
Add Comment
Please, Sign In to add comment