Logging the User In - Implementation
1 - Route Name
Let's add the route and the controller in first.
POST /api/v1/auth/login
File: src/routes/index.js
const express = require('express')
const router = express.Router()
const userRoutes = require('./user.route')
const authRoutes = require('./auth.route')
function getRouter() {
router.use('/users', userRoutes)
router.use('/auth', authRoutes) // our new route
return router
}
module.exports = getRouter
File: src/routes/auth.route.js
const express = require('express')
const router = express.Router()
const { logUserIn } = require('../controllers/auth')
router.post('/login', logUserIn)
module.exports = router
File: src/controllers/auth/logUserIn.js
const catchExceptions = require('../utils/catchExceptions')
const logUserIn = catchExceptions(async (req, res, next) => {
// Code goes here...
})
2 - Input Request
Next we'll add in the DTO, let's call it loginUserRequestDto
.
const ApiException = require('../utils/ApiException')
const fields = ['email', 'password']
const loginUserRequestDto = (data) => {
const errors = []
fields.forEach((field) => {
if (!(field in data)) {
errors.push(`This DTO's property is required: ${field}.`)
}
})
if (errors.length > 0) {
throw new ApiException({
status: 'error',
code: 422,
message: 'loginUserRequestDto failed.',
data: null,
errors
})
}
return data
}
module.exports = loginUserRequestDto
3 - Middleware
None.
4 - Validation
Now time for the validator.
const Validator = require('validatorjs')
const ApiException = require('../utils/ApiException')
/**
* @param {*} data {
* - email
* - password
* }
*
* @returns Validator
*/
const loginUserValidator = (data) => {
const rules = {
email: 'required|email',
password: 'required'
}
const validator = new Validator(data, rules)
if (validator.fails()) {
let errors = []
for (const field in validator.errors.errors) {
errors = errors.concat(validator.errors.errors[field])
}
throw new ApiException({
message: 'There were errors with the validation',
status: 'error',
code: 400,
data: null,
errors: validator.errors.errors
})
}
return validator
}
module.exports = loginUserValidator
5 - Domain
For checking if there is a match in our database, we'll use our userModel
that was created in the last section.
We'll add a new method called findUserByEmailAndPassword
which will simply use our userModel
to do a find in our database.
File: src/domain/services/userRepository.js
const UserModel = require('../models/user.model')
/**
*
* @param {*} user {
* - name
* - email
* - password
* }
*
* @returns user
*/
const findUserByEmailAndPassword = async (userData) => {
const foundUser = await UserModel.findOne(userData)
return foundUser
}
Once we have database query done, we'll add a new method called loginUser
and use it in our authService
. Notice here that we throw and exception if we do not find any users in the database. This would mean that the client's request has failed.
File: src/domain/services/authService.js
/**
* @returns user
*/
const loginUser = async (user) => {
const loginUser = await userRepository.findUserByEmailAndPassword(user)
if (!loginUser) {
throw new ApiException({
status: 'error',
code: 400,
message: `Invalid credentials, please try a different email and password combination.`,
data: null,
errors: [
`Invalid credentials, please try a different email and password combination.`
]
})
}
return loginUser
}
6 - Events
None.
7 - Response
Now to put everything all together. We'll reuse our userResponseDto
from last section and log the user into our session with a simple req.session.user
.
Once again, our code looks nice and clean 😎.
/**
* Logs the user in and set a session for it.
*/
const logUserIn = catchExceptions(async (req, res) => {
const loginUserRequest = loginUserRequestDto(req.body)
loginUserValidator(loginUserRequest)
// if the user's email and password match in our database
// then set the current session to that user
const loggedInUser = await authService.loginUser(loginUserRequest)
// If there we find a user with authService.loginUser, then
// we'll set the current session to that user
req.session.user = loggedInUser
const userDto = userResponseDto(loggedInUser)
res.status(200).json(
globalResponseDto({
status: 'success',
code: 200,
message: `The user has successfully logged in.`,
data: userDto,
errors: null
})
)
})
module.exports = logUserIn
Last updated