---
# System prepended metadata

title: Validación de usuario (Login)

---

# 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 };
```