{"size": 3387, "ext": "js", "max_stars_repo_path": "controllers/authentication.js", "max_stars_repo_name": "allku/AllkuOverlord", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "controllers/authentication.js", "max_issues_repo_name": "allku/AllkuOverlord", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "controllers/authentication.js", "max_forks_repo_name": "allku/AllkuOverlord", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 23.5208333333, "max_line_length": 70, "alphanum_fraction": 0.6126365515}
const db = require('../models')
const PasswordValidator = require('password-validator')
const { validationResult } = require('express-validator')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
const e = require('../util/errorWriter')

// @desc    Register user
// @route   POST /overlord/rest/v1/auth/register
// @access  Public
exports.register = async (req, res, next) => {
  const errors = validationResult(req)

  if (!errors.isEmpty()) {
    return res.status(500).json({
      message: e.message(errors)
    })
  }

  const { username, password, email } = req.body

  const schema = new PasswordValidator()
  schema.is().min(8)
    .is().max(30)
    .has().uppercase()
    .has().lowercase()
    .has().digits(1)
    .has().not().spaces()
    .is().not().oneOf([username, 'Passw0rd'])

  if (!schema.validate(password)) {
    return res.status(500).json({
      message: 'La contraseña debe contener al menos 8 caracteres, ' +
      'letras mayúsculas y minísculas, números, sin espacios, ' +
      'no debe ser la misma que el usuario'
    })
  }

  const oneUser = await db.User.findOne({
    where: { username: username }
  })

  // If exist, return existed true
  if (oneUser) {
    return res.status(200).json({
      username: oneUser.username,
      status: oneUser.status,
      existed: true
    })
  }

  const user = db.User.build({
    username: username,
    password: await bcrypt.hash(password, bcrypt.genSaltSync(8)),
    email: email,
    status: 'Activo'
  })

  // If success create, return with exsited false
  await user.save()
    .then(() => res.status(201).json({
      username: user.username,
      status: user.status,
      existed: false
    }))
    .catch((err) => {
      const errorMessage = e.write(err, __filename, 'User register')
      res.status(501).json({
        message: errorMessage
      })
    })
}

// @desc    Login user
// @route   POST /overlord/rest/v1/auth/login
// @access  Public
exports.login = async (req, res, next) => {
  const errors = validationResult(req)

  if (!errors.isEmpty()) {
    return res.status(500).json({
      message: e.message(errors)
    })
  }

  const { username, password } = req.body

  const user = await db.User.findOne({
    where: { username: username }
  })

  if (!user) {
    return res.status(401).json({
      message: 'Credenciales inválidas'
    })
  }

  // Compare the password entry between password user from database
  const isMatch = await bcrypt.compare(password, user.password)

  if (!isMatch) {
    return res.status(401).json({
      message: 'Credenciales inválidas'
    })
  }

  // Get roles of user
  const roles = await db.UserRole.findAll({
    attributes: ['rolename'],
    where: { username: user.username },
    order: [
      ['rolename', 'ASC']
    ]
  })

  // Convert roles query in array
  const roleArray = []
  for (const i in roles) {
    roleArray.push(roles[i].rolename)
  }
  // console.log(roleArray)

  try {
    const token = jwt.sign(
      {
        username: user.username,
        status: user.status,
        roles: roleArray
      }
      , process.env.JWT_SECRET, {
        expiresIn: process.env.JWT_EXPIRE
      })

    return res.status(200).json({
      token
    })
  } catch (err) {
    e.write(err, __filename, 'Error in jwt.sign')
    return res.status(501).json({
      message: 'Error al firmar con JWT'
    })
  }
}
