John
John

Reputation: 93

Nodejs controller is being messy

I'm new to javascript, node.js (or backend at all). I am trying to create a controller for the login page requests and I am confused about getting data from the MYSQL table and User Authentication and working with JWT package !

In my Controller, I first check if the user input is available in the user table (with a simple stored procedure), then I compare the database password and the user input, after this I want to create a token and with limited time. (I have watched some tutorial videos about JWT and there is no problem with it), my main problem is to figure out how to write a proper controller with this functions?

I have 2 other questions:

1.Is it the right and secure way to get data from MySQL table inside the route? Or should I create a JS class for my controller? (I'm a bit confused and doubtful here)

2.Assuming that comparePassword() returns true, how can I continue coding outside of the db.query callback function scope? Because I have to execute comparePasssword() inside db.query callback

loginController.js :

const { validationResult } = require('express-validator');
const bcrypt = require('bcrypt');
const db = require('../../sqlConnection')

let comparePassword = (dbPass, inputPass) => {
  bcrypt.compare(inputPass, dbPass, function(err, result) {
     console.log(result)
 });
}

// for get request
exports.getController = (req, res) => {
  res.send('login')
}

// for post request
exports.postController = (req, res) => {
  let errors = validationResult(req)

  if(!errors.isEmpty()) {
     res.status(422).json({ errors: errors.array() })
  }
  
  // find data from MYSQL table

  let sql = `CALL findUser(?)`
  db.query(sql, [req.body.username], (err, res) => {
     if(err) console.log(err)
     //console.log(Object.values(JSON.parse(JSON.stringify(res[0]))))
     var data = JSON.stringify(res[0])
     data = JSON.parse(data).find(x => x)
     data ? comparePassword(data.password, req.body.password) : res.status(400).send('cannot find 
     user')
  })

  res.send('post login')
 }

login.js :

const express = require('express')
const router = express.Router()
const { check } = require('express-validator');
const loginCont = require('../api/controllers/loginController')

router.route('/')
  .get(
     loginCont.getController
   )
   .post(
       [
        check('username').isLength({min: 3}).notEmpty(), 
        check('password').isLength({min: 4}).notEmpty()
       ],
       loginCont.postController
    )

 module.exports = router

Upvotes: 2

Views: 158

Answers (1)

Marcel Kohls
Marcel Kohls

Reputation: 1857

In my point of view, looks like there is no easy answer for your question so I will try to give you some directions so you can figure out which are the gaps in your code.

First question: MySQL and business logic on controller

In a design pattern like MVC or ADR (please take a look in the links for the flow details) The Controllers(MVC) Or Actions(ADR) are the entry point for the call, and a good practice is to use these entry points to basically:

  • Instantiate a service/class/domain-class that supports the request;
  • Call the necessary method/function to resolve what you want;
  • Send out the response;

This sample project can help you on how to structure your project following a design pattern: https://riptutorial.com/node-js/example/30554/a-simple-nodejs-application-with-mvc-and-api

Second question: db and continue the process

For authentication, I strongly suggest you to take a look on the OAuth or OAuth2 authentication flow. The OAuth(2) has a process where you generate a token and with that token you can always check in your Controllers, making the service a lot easier.

Also consider that you may need to create some external resources/services to solve if the token is right and valid, but it would facilitate your job.

This sample project should give you an example about how to scope your functions in files: https://github.com/cbroberg/node-mvc-api

Summary

You may have to think in splitting your functions into scoped domains so you can work with them in separate instead of having all the logic inside the controllers, then you will get closer to classes/services like: authenticantion, user, product, etc, that could be used and reused amount your controllers.

I hope that this answer could guide you closer to your achievements.

Upvotes: 1

Related Questions