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