Untitled

 avatar
unknown
javascript
2 years ago
14 kB
5
Indexable
var express = require('express');
var router = express.Router();
const modeloPiscina = require("../models/piscina")
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const { check, validationResult, body } = require('express-validator');

var usuario = "paco"
var clave = "falsa"
var tokenfalso = "mentira"
/**
 * se utiliza un array de piscinas para almacenar los recusos
 * no es el objetivo del módulo el trabajar con base de datos
 */
var piscinas = new Array();
var contador = 0;

function init(){
  let tempopiscina=  new modeloPiscina.Piscina("Torre Stark", "Iron Man", new Date().toISOString().slice(0, 10))
  piscinas.push(tempopiscina);
  contador++;
  tempopiscina.Id = contador;
  
  tempopiscina= new modeloPiscina.Piscina("C/Titan", "Thanos", new Date().toISOString().slice(0, 10))
  piscinas.push(tempopiscina);
  contador++;
  tempopiscina.Id = contador;

  tempopiscina=new modeloPiscina.Piscina("Avda Dimensión Espejo", "Doctor Strange", new Date().toISOString().slice(0, 10))
  piscinas.push(tempopiscina);
  contador++;
  tempopiscina.Id = contador;
  }
/**
 * Añadir el código necesario para validar los campos de entrada y generar 
 * un token
 */

//! ====== HECHO ======

function validate() {
  if (usuario === "paco" || clave === "falsa") {
    console.log("¡Bienvenido " + usuario + "!");
    return true;
  }else {
    console.log("Por favor ingrese usuario y contraseña");
    return false;
  }
}

// Token con JWT

const payload = {
  usuario: "paco",
  clave: "falsa"
};

const secret = "mi_clave_secreta";

const tokenJWT = jwt.sign(payload, secret);

console.log(tokenJWT);

router.post("/login",
  (req, res) => {
    return res.json(validate() + " || " + tokenJWT);
  })

/**
 * Alta de una nueva piscina, validar que se tiene permisos (enviar el token), comprobar los parámetros y desinfectar los mismos
 */

//! ====== HECHO ======

//? Se utiliza la librería express-validator para validar los parámetros y xss para desinfectarlos

//? Explicación:
//?  Se importan las librerías express-validator y xss.
//?  En el middleware de la ruta se utiliza body de express-validator para validar que los campos direccion y propietario no estén vacíos y se les aplica el método trim para quitar espacios en blanco al principio y al final, y escape para escapar caracteres especiales.
//?  Se verifica si existen errores de validación utilizando validationResult de express-validator y se devuelve un error 400 con los errores si es el caso.
//?  Se utiliza xss para desinfectar los valores de direccion y propietario.
//?  Se crea la nueva instancia de Piscina utilizando los valores validados y desinfectados.
//?  Se incrementa el contador y se asigna el nuevo id a la instancia de Piscina.
//?  Se envía la respuesta con la nueva instancia de Piscina y el token. 


const { body, validationResult } = require('express-validator');
const xss = require('xss');

router.post(
  '/piscina',
  [
    body('direccion').notEmpty().trim().escape(),
    body('propietario').notEmpty().trim().escape(),
  ],
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const direccion = xss(req.body.direccion);
    const propietario = xss(req.body.propietario);
    const fechaCreacion = new Date().toISOString().slice(0, 10);

    const piscina = new modeloPiscina.Piscina(direccion, propietario, fechaCreacion);
    piscinas.push(piscina);
    contador++;
    piscina.Id = contador;
    res.json({ piscina, token: tokenJWT });
  }
);

/**
 * 
 * Borrar una piscina, validar que se tiene permisos (enviar el token), comprobar los parámetros y desinfectar los mismos
 */

//! ====== HECHO ======

//? Se utiliza la librería jsonwebtoken para verificar el token y express-validator para validar los parámetros y xss para desinfectarlos

//?  Explicación:
//?   Se importan las librerías jsonwebtoken, express-validator y xss.
//?   En el middleware de la ruta se utiliza param de express-validator para validar que el parámetro id sea un número entero.
//?   Se verifica si existen errores de validación utilizando validationResult de express-validator y se devuelve un error 400 con los errores si es el caso.
//?   Se recupera el token de autenticación del encabezado Authorization de la solicitud HTTP y se verifica utilizando jsonwebtoken.
//?   Se comprueba si el usuario tiene permisos para realizar la acción. En este caso, se verifica si el campo role del token decodificado es "admin".
//?   Se recupera el valor del parámetro id y se busca el índice de la piscina correspondiente en el arreglo piscinas.
//?   Si no se encuentra la piscina, se devuelve un error 404 con un mensaje.
//?   Si se encuentra la piscina, se elimina del arreglo piscinas.
//?   Se envía una respuesta JSON que incluye el número de elementos eliminados del arreglo.

const jwt = require('jsonwebtoken');
const { param, validationResult } = require('express-validator');
const xss = require('xss');

router.delete(
  '/piscina/:id',
  [
    param('id').isInt().toInt(),
  ],
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const token = req.headers.authorization;
    if (!token) {
      return res.status(401).json({ message: 'No se ha proporcionado un token de autenticación' });
    }

    try {
      const decoded = jwt.verify(token, 'mi_clave_secreta');
      if (decoded.role !== 'admin') {
        return res.status(403).json({ message: 'No tiene permisos para realizar esta acción' });
      }
    } catch (err) {
      return res.status(401).json({ message: 'Token inválido o expirado' });
    }

    const id = req.params.id;
    const index = piscinas.findIndex(piscina => piscina.Id === id);
    if (index === -1) {
      return res.status(404).json({ message: 'No se encontró la piscina con el id especificado' });
    }

    const length_antes = piscinas.length;
    piscinas.splice(index, 1);
    const length_despues = piscinas.length;

    res.json({ deleted: length_antes - length_despues });
  }
);

/**
 *  Datos de todas las piscinas, comprobar si se tiene permisos. 
 * */

//! ====== HECHO ======

//? Se utiliza la librería jsonwebtoken para verificar el token

//?  Explicación:
//?   Se importa la librería jsonwebtoken.
//?   Se define la ruta GET /piscina.
//?   Se recupera el token de autenticación del encabezado Authorization de la solicitud HTTP y se verifica utilizando jsonwebtoken.
//?   Se comprueba si el usuario tiene permisos para realizar la acción. En este caso, se verifica si el campo role del token decodificado es "admin".
//?   Se envía una respuesta JSON que incluye el arreglo piscinas.

const jwt = require('jsonwebtoken');

router.get('/piscina', (req, res) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ message: 'No se ha proporcionado un token de autenticación' });
  }

  try {
    const decoded = jwt.verify(token, 'mi_clave_secreta');
    if (decoded.role !== 'admin') {
      return res.status(403).json({ message: 'No tiene permisos para realizar esta acción' });
    }
  } catch (err) {
    return res.status(401).json({ message: 'Token inválido o expirado' });
  }

  res.json(piscinas);
});

/**
 *  Datos de una piscina concreta, Comprobar si se tiene permisos y el parámetro es correcto. 
 * */

//! ====== HECHO ======

//? Se utiliza la librería jsonwebtoken para verificar el token:

//?  Explicación:
//?    Se importa la librería jsonwebtoken.
//?    Se define la ruta GET /piscina/:id.
//?    Se recupera el token de autenticación del encabezado Authorization de la solicitud HTTP y se verifica utilizando jsonwebtoken.
//?    Se comprueba si el usuario tiene permisos para realizar la acción. En este caso, se verifica si el campo role del token decodificado es "admin".
//?    Se comprueba si el parámetro id es un número entero válido. Si no lo es, se envía una respuesta de error.
//?    Se busca la piscina correspondiente al id proporcionado en el arreglo piscinas. Si no se encuentra, se envía una respuesta de error.
//?    Se envía una respuesta JSON que incluye los datos de la piscina correspondiente.

const jwt = require('jsonwebtoken');

router.get('/piscina/:id', (req, res) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ message: 'No se ha proporcionado un token de autenticación' });
  }

  try {
    const decoded = jwt.verify(token, 'mi_clave_secreta');
    if (decoded.role !== 'admin') {
      return res.status(403).json({ message: 'No tiene permisos para realizar esta acción' });
    }
  } catch (err) {
    return res.status(401).json({ message: 'Token inválido o expirado' });
  }

  const id = parseInt(req.params.id);
  if (isNaN(id)) {
    return res.status(400).json({ message: 'El parámetro ID debe ser un número entero' });
  }

  const piscina = piscinas.find(element => element.Id === id);
  if (!piscina) {
    return res.status(404).json({ message: 'No existe la piscina con el ID proporcionado' });
  }

  res.json(piscina);
});



/**
 * Alta de una nueva medición a una piscina, validar que se tiene permisos (enviar el token), comprobar los parámetros y desinfectar los mismos
 */

//! ====== HECHO ======

//? Se utiliza la librería jsonwebtoken para verificar el token y se comprueban los parámetros antes de crear la medición:

//?  Explicación:
//?    Se importa la librería jsonwebtoken.
//?    Se define la ruta POST /piscina/:id/medicion.
//?    Se recupera el token de autenticación del encabezado Authorization de la solicitud HTTP y se verifica utilizando jsonwebtoken.
//?    Se comprueba si el usuario tiene permisos para realizar la acción. En este caso, se verifica si el campo role del token decodificado es "admin".
//?    Se comprueba si el parámetro id es un número entero válido.

const jwt = require('jsonwebtoken');

router.post('/piscina/:id/medicion', (req, res) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ message: 'No se ha proporcionado un token de autenticación' });
  }

  try {
    const decoded = jwt.verify(token, 'mi_clave_secreta');
    if (decoded.role !== 'admin') {
      return res.status(403).json({ message: 'No tiene permisos para realizar esta acción' });
    }
  } catch (err) {
    return res.status(401).json({ message: 'Token inválido o expirado' });
  }

  const id = parseInt(req.params.id);
  if (isNaN(id)) {
    return res.status(400).json({ message: 'El parámetro ID debe ser un número entero' });
  }

  const piscina = piscinas.find(element => element.Id === id);
  if (!piscina) {
    return res.status(404).json({ message: 'No existe la piscina con el ID proporcionado' });
  }

  const ph = parseFloat(req.body.ph);
  if (isNaN(ph) || ph < 0 || ph > 14) {
    return res.status(400).json({ message: 'El valor de pH debe ser un número decimal entre 0 y 14' });
  }

  const cloro = parseFloat(req.body.cloro);
  if (isNaN(cloro) || cloro < 0) {
    return res.status(400).json({ message: 'El valor de cloro debe ser un número decimal positivo' });
  }

  const gramos_ph = parseInt(req.body.gramos_ph);
  if (isNaN(gramos_ph) || gramos_ph < 0) {
    return res.status(400).json({ message: 'El valor de gramos de pH debe ser un número entero positivo' });
  }

  const gramos_cloro = parseInt(req.body.gramos_cloro);
  if (isNaN(gramos_cloro) || gramos_cloro < 0) {
    return res.status(400).json({ message: 'El valor de gramos de cloro debe ser un número entero positivo' });
  }

  const antialgas = req.body.antialgas ? true : false;

  const fluoculante = req.body.fluoculante ? true : false;

  const medicion = new modeloPiscina.Medicion(new Date().toISOString().slice(0, 10), ph, cloro, gramos_ph, gramos_cloro, antialgas, fluoculante);
  piscina.addMedicion(medicion);

  res.json(medicion);
});

/**
* Borrar una medición, validar que se tiene permisos (enviar el token), comprobar los parámetros y desinfectar los mismos
*/

//! ====== HECHO ======

//? Este código primero comprueba que el token enviado sea válido, luego busca la piscina a la que pertenece la medición y comprueba que exista, después busca la medición dentro de la piscina y comprueba que exista, y finalmente borra la medición de la piscina. Si en alguna de estas comprobaciones se detecta un error, se devuelve una respuesta con un mensaje de error correspondiente.

router.delete(
  '/piscina/:idpiscina/medicion/:id',
  (req, res) => {
    const idPiscina = parseInt(req.params.idpiscina);
    const idMedicion = parseInt(req.params.id);
    const token = req.header('Authorization');
    
    // Comprobamos que el token sea válido
    if (token !== 'miTokenDeAutenticacion') {
      res.status(401).json({ error: "No tienes permisos para realizar esta operación" })
      return;
    }
    
    // Buscamos la piscina
    const piscina = piscinas.find(p => p.Id === idPiscina);
    
    if (!piscina) {
      res.status(404).json({ error: "No existe la piscina" });
      return;
    }
    
    // Buscamos la medición
    const medicion = piscina.Mediciones.find(m => m.Id === idMedicion);
    
    if (!medicion) {
      res.status(404).json({ error: "No existe la medición" });
      return;
    }
    
    // Borramos la medición
    piscina.Mediciones = piscina.Mediciones.filter(m => m.Id !== idMedicion);
    
    res.json({ message: "Medición eliminada correctamente" });
  }
);

/**
*  Obtener una medición concreta. 
* */

//! ====== HECHO ======

//? Este código ya obtiene la medición concreta ya que esta ruta utiliza los parámetros idpiscina e id para identificar la piscina y la medición concretas.

router.get('/piscina/:idpiscina/medicion/:id', function (req, res, next) {
  var piscina = piscinas.find(element => element.Id == parseInt(req.params.idpiscina));
  var medicion;
  if (piscina == undefined) {
    res.status(404).json({ error: "No existe la piscina" })
  } else {
    medicion = piscina.Mediciones.find(element => element.Id == parseInt(req.params.id))
    if (medicion == undefined) {
      res.status(404).json({ error: "No existe la medicion" })
    } else {
      res.json(medicion)
    }
  }
});

module.exports = {router, init};