# Validación de usuario (Login) A continuación se muestra el código de la validación de usuario, en el cual se verifica que el usuario exista en la base de datos y que la contraseña sea correcta dentro de la API. Para lograr esto necesitamos tener 3 endpoints en la API: - `create` para crear/modificar un nuevo usuario - `assignPassword` para asignarle una constraseña a un usuario - `validate` para validar que el usuario y contraseña ingresados son válidos En primera instancia, necesitamos registrar una la librería `bcrypt`: ```typescript yarn add bcrypt ``` Luego creamos el router `user.ts` con los 3 endpoints antes mencionados (dentro de la carpeta `/src/routes`): ```typescript import { Router } from "express"; import { create, assignPassword, validate, } from "../controllers/user"; const UserRouter = Router(); UserRouter.post("/create", create); UserRouter.put("/assignPassword/:id", assignPassword); UserRouter.post("/validate", validate); export default UserRouter; ``` Posteriormente creamos el controlador `user.ts` (dentro de la carpeta `/src/controllers`): ```typescript import createLogger from "../utils/logger"; import * as User from "../models/user"; import * as Person from "../models/person"; const create = async (req: any, res: any) => { try { const { rut, name, paternal_lastname, maternal_lastname, address, district_id, email, phone, } = req.body; const personByRutResponse = await Person.getByRut(rut); if (personByRutResponse.success) { return res.status(500).json({ error: "Error searching person" }); } let personResponse; if (personByRutResponse.data) { const { id: person_id } = personByRutResponse.data; personResponse = await Person.updateById( person_id, name, paternal_lastname, maternal_lastname, address, district_id, email, phone ); } else { personResponse = await Person.insert( rut, name, paternal_lastname, maternal_lastname, address, district_id, email, phone ); } if (!personResponse.success) { return res.status(500).json({ error: "Error registering person" }); } const { id: person_id } = personResponse.data; const userResponse = await User.insert(person_id); if (!userResponse.success) { return res.status(500).json({ error: "Error creating user" }); } createLogger.info({ controller: "user/insert", data: personResponse.data, }); return res.status(200).json(personResponse); } catch (e) { createLogger.error({ controller: "user/insert", error: (e as Error).message, }); return res.status(500).json({ error: "Error creating user" }); } } }; const assignPassword = async (req: any, res: any) => { try { const { id } = req.params; const { password } = req.body; const result = await User.assignPassword(id, password); if (!result.success) { createLogger.error({ model: "user/assignPassword", method: "POST", error: result.error, }); return res.status(500).json({ error: "Error inesperado" }); } res.status(200).json(result.data); } catch (e) { createLogger.error({ model: "user/assignPassword", method: "POST", error: (e as Error).message, }); return res.status(500).json({ error: "Error inesperado" }); } }; const validate = async (req: any, res: any) => { try { const { email, password } = req.body; const result = await User.validate(email, password); if (!result.success) { createLogger.error({ model: "user/validate", method: "POST", error: result.error, }); return res.status(500).json({ error: "Error inesperado" }); } if (result.success) { if (result.data.isValid) { res.status(200).json(result.data); } else { res.status(403).json({ error: "User not valid" }); } } } catch (e) { createLogger.error({ controller: "user/validate", method: "POST", error: (e as Error).message, }); return res.status(500).json({ error: "Error inesperado" }); } }; export { create, assignPassword, validate, }; ``` Finalmente el modelo sería como sigue: ```typescript import db from "../utils/db"; import createLogger from "../utils/logger"; import bcrypt from "bcrypt"; import { RowDataPacket } from "mysql2/promise"; import { _insert, _asisgnPassword, _validate, } from "../queries/user"; const create: any = async (values: any) => { try { createLogger.info({ model: "user/create", input: { values }, }); const { person_id } = values; const [result] = await db.query(_insert, [ person_id ]); return { success: true, data: { id: result["insertId"] }, error: null, }; } catch (e) { return { success: false, data: null, error: (e as Error).message }; } }; const assignPassword: any = async (id: string, password: string) => { try { createLogger.info({ model: "user/assignPassword", input: { id, password }, }); const saltRounds = 10; const hash = await bcrypt.hash(password, saltRounds); const [rows] = await db.query(_asisgnPassword, [hash, id, id]); return { success: true, data: (<RowDataPacket>rows)[1][0], error: null }; } catch (e) { return { success: false, data: null, error: (e as Error).message }; } }; const validate: any = async (login: string, password: string) => { try { createLogger.info({ model: "user/validate", input: { login, password }, }); const [rows] = await db.query(_validate, [login]); const { id, person_id, rut, name, paternalLastName, maternalLastName, address, district_id, email, phone, hash, } = (<RowDataPacket>rows)[0]; const isValid = await bcrypt.compare(password, hash); return { success: true, data: { id, person_id, rut, name, paternalLastName, maternalLastName, address, district_id, email, phone }, error: null, }; } catch (e) { return { success: false, data: null, error: (e as Error).message }; } }; export { insert, assignPassword, validate }; ```