Está en la página 1de 148

CLASE 31

Estamos en una nueva clase que sería la continuación del módulo número 5 que va
a ser de Express validator, pero también vamos a hablar de middlewares, que
prácticamente ya lo veníamos usando, utilizando middlewares de otras personas o
de terceros. Pero ya lo implementamos, así que vamos a ver de qué se trata, cómo
se los puede utilizar, si se los puede utilizar de forma Global en nuestra aplicación o
si se lo puede utilizar en una ruta.

Justamente los middlewares serían lo que está entre medio de lo que va a ser el
pedido de la ruta, ,ya sea la petición a home, a productos, o listado de productos,
lo que sea y la resolución del controlador.Va a ser un paso intermedio.

Justamente, agregamos middlewares para ir sacando un poco de lo que son las


responsabilidades de un solo lugar. Así que vamos a tratar de que todas las cosas
que tengan un objetivo específico, por ejemplo multer, que lo usamos para
imágenes, lo sacamos de la ruta para crearlo o para agregarlo a una carpeta que se
llama middlewares. Bueno, la idea es implementar todo ese tipo de servicios en
una carpetita que se llama middlewares. En este caso, (entre paréntesis) multer
solamente lo usamos en las rutas, no lo usamos de forma global.
middlewares de aplicación

O esté ingresando.

Lo implementamos justamente usando el app.use. Cuando usamos el use,


queremos indicar que vamos a agregar un middleware o una configuración nueva a
nuestro servidor. Para utilizar este este tipo de middlewares, necesitamos
funciones que tengan el request el response y luego a algo nuevo que es next.
Este middleware puede hacer lo que sea: puede por ejemplo autentificar si el
usuario está logueado o si el usuario es administrador y demás. Y si tiene permisos,
que me deje continuar con todo el proceso de crear un producto o de ver la página
del perfil o lo que sea. Y en el caso de que no coincida con lo que estamos
esperando, podemos redireccionar a otro lugar o cortar la ejecución. Están muy
buenos los middlewares para validar formularios y demás.
Next()

Como vemos, next es un callback que se va a encargar de apilar todos los


middlewares. Es decir, si tenemos 10 middlewares, se va a ejecutar el primero de
la pila. Si nosotros le ponemos un next al final del código, va a pasar al segundo y
así sucesivamente, siempre y cuando tenga el next. Si no le agregamos el next, la
página o el servidor va a quedar colgado esperando algo, así que es muy importante
agregarle el next a los middlewares.

Acá tenemos algunos middlewares que ya utilizamos. Cómo ser el primero, que
configuraba la carpeta donde estaban todos nuestros archivos estáticos, que en
nuestro caso están en public. Y luego tenemos otro, que sería la configuración de
las rutas. Este enrutador sería para productos, pero en este caso no tiene un prefijo
como lo usamos nosotros. Este es un middlewares de ruta. O sea un middlewares
de aplicación global, que está configurando rutas.
Middleware para errores de ruta: error 404

Acá van a ver un ejemplo de un middlewares que se maneja para los errores, que
ya lo habíamos visto un par de clases anteriores, porque lo usábamos de una forma
diferente. Esta sería otra forma: Si es que ingresa un status 404, va a renderizar la
página esa, es decir la página 404.
Middlewares a nivel de rutas

Los middlewares globales van en app.js o en nuestro entry Point. Los


middlewares de ruta, van en medio de lo que sería el pedido y la respuesta o lo
que sea que haga ese controlador, pero van en el centro.
Cuando habla de escribir el código en un archivo aparte, se refiere a nuestra
carpetita middlewares, y requerirlo dónde lo vamos a usar. En la función del
ejemplo, rutaDeUsuario, vamos a verificar si el usuario está logueado.

¿Cómo verificaría? ¿Qué podemos usar de la programación de javascript para


verificar o para buscar un condicional, si cumple con la condición o no. ¿Cómo
manejamos las condiciones? Por ejemplo si el usuario es administrador o si el
usuario está logueado, si cumple con ese If, que me ejecute alguna acción. Acá
empieza por si no está logueado lo enviamos al login nuevamente, a la vista y si
está logueado, dejamos que se ejecute next y se sigan ejecutando las demás cosas,
que quizás es un inicio de sesión y la vista de su perfil de usuario o el acceso al
administrador o lo que sea.
Configuración de un middleware a nivel de rutas

Supongamos que al middlewares rutaDeUsuario, lo creamos en un archivo aparte,


luego no olvidemos que para que sea un módulo necesitamos exportarlo. Una vez
exportado, ya lo tenemos listo para requerirlo.

Hacemos un require, le indicamos dónde está ese middlewares, y cada vez que lo
necesitamos usar simplemente lo agregamos.

Así que, antes de que se ejecute usersController.profile, va a preguntar si es que


el usuario está logueado.

Vamos a hacer un ejemplo del uso de un middleware de ruta pero para


express-validator, y vamos a usar la misma validación para los dos formularios de
productos, como para ponerles un ejemplo de por qué nos recomiendan que lo
hagamos en una carpeta aparte.

Express-validator
Express-validator es una librería que se descarga del node package manager
(npm), que sería de la página de npm, y es una librería de terceros que ya viene
con toda la lógica lista para que la utilicemos para validar formularios.

Necesitamos instalar Express-validator. Crear un array con la validación de cada


uno de los inputs de nuestro formulario. Supongamos que tenemos name, price y
password, podemos validar los tres, que uno sea de tipo numérico, que el otro sea
de tipo alfabético, que no esté vacío, que sea un email, que tenga una contraseña
de más de X caracteres, etc. Se puede hacer lo que queramos.

Veamos ese paso a paso.


Instalando express-validator

Se instala con npm install express-validator.

Nuestro formulario

Este sería el formulario. Como ven, cada formulario tiene un name, que en el primer
caso es name, pero después tenemos el otro que es un email, y el que sigue es un
password.
Las validaciones

Así que cada vez que queramos validar algo, vamos a usar por ejemplo {check} o
{Body}, cualquiera de los dos va a funcionar.

El método Check()

Y dentro del objeto vamos agregando todo lo que queremos que se valide. Por
ejemplo, en el campo name, quiero que me me valide que no esté vacío. Si es que
el usuario lo envía vacío, que vaya generando un error. Que me vaya guardando
ese error, para que después lo pueda mostrar.
Acá tenemos un listado de todas las cosas que se pueden hacer, igual hay
muchísimas más. Por ejemplo este tiene que no sea vacío, que la longitud sea
entre 5 y 10 caracteres, que sea un email y que sea un número entero, por
ejemplo. No tiene mucho sentido, ya que no puede ser un email y un número entero.
Y en este link van a encontrar muchas más validaciones. si es booleano, si es una
fecha, si es de hexadecimal (un String con hexadecimal), si es numérico.

Una vez que tenemos todo definido de lo que queremos validar, ya podemos ir
exportando.

El array de validaciones
Algo así quedaría. Supongamos que tenemos name, email y password. Podemos
validar que por ejemplo el name o el input que se llama name no puede estar vacío.

Mensajes de error

El withMessage, hace que cada vez que no cumpla con alguna de estas cosas, me
genere el mensaje. Por ejemplo, .notEmpty(), el mensaje que va a mandar es:
debes completar el nombre. Después si se genera algo con el error que sea
menor a cinco caracteres, el mensaje será: el nombre debe tener al menos cinco
caracteres. Esto sirve un montón para que sea más descriptivo el tema del error
para el usuario.

Cortando la cadena de validación con bail


Luego agrega algo que se llama .bail, que lo que va a hacer es cortar la validación
aquí (Debes completar el email), es decir, no continúa validando el resto de
campos que se viene más abajo sino que te genera el primer error y te dice Bueno,
corregime esto. y después sigo validando los demás. Está bueno cuando son una
lista de 20 Campos, ir cortando uno por uno, para que se vaya haciendo la
validación de forma ordenada.

En caso de que cumpla y ya no esté vacío, va a pasar recién al siguiente y ahí se va


a fijar si cumple con el requisito de que sea un email válido.

El array de validaciones completo

Una vez que ya tenemos armado el array con todas las validaciones, en este caso lo
guardamos en una constante, o la guardamos como nosotros queramos, pero lo
exportamos para que se convierta en un módulo. Porque vamos a usarlo en un
middlewares y después vamos a exportar esa validación.
Agregando las validaciones en las rutas

Cuando ya tengamos listo el array con todas las validaciones, lo podemos agregar
como middlewares de ruta. Así que agregamos ahí -(en validateRegister)- todas
las validaciones, es decir, cuando el usuario haga clic en el botón enviar o crear
producto, o lo que sea, (en este caso el registro), cuando él de click en el botón
registrarse, va a pasar primero por la validación validateRegister. Si es que hay
errores, lo que va a pasar es que todos esos errores se van a ir guardando en un
objeto y después va a pasar por userController.processRegister y es donde
podemos atrapar los errores y manipularlos.

Estos controles solamente se hace cuando se va por ejemplo a crear un producto,


actualizar un producto, o loguearnos.Todo lo que sea con manipulación de
formularios.

En este caso, como ven acá, estamos usándolo en un post, pero puede ser en un
put también.
Ya estamos en el paso número 4.

Ya instalamos express-validator, ya creamos una array con todas las cosas que
queríamos validar, ya lo agregamos ahí a la ruta como middleware, es decir entre la
ruta y el controlador.

Nos falta verificar si es que hay errores en la validación del controlador, y luego
enviarlos a la vista.

Hasta acá solamente se está guardando en errors, en un resultado en sí, pero no lo


estamos usando de ninguna forma. Vamos a usar otro objeto, otro Método de
express-validator, que se llama validationResult.

Express Validator Avanzado


Las validaciones en el controlador: validationResult

En este caso, nos vamos a userControllers, al controlador en sí, requerimos


express-validator, y luego, en el controlador donde queremos utilizarlo, o en el
método, vamos a guardar validationResult(req).

El validationResult de lo que viene del request, lo vamos a guardar en una


variable que le podemos llamar errors, errores, como nosotros queramos. Pero va
a ser el que va a guardar todo el listado de errores. De cada campo, los errores que
contiene.

El último paso que hicimos fue meterlo como middleware en la ruta. Este paso va a
ser, utilizar toda esa información que se va guardando. Así que nos vamos al
userControllers, requerimos express-validator, y luego en el post de register o
processRegister, o como le queramos llamar, en ese método, vamos a guardar en
una variable el resultado de validationResult. Y esto nos va a traer un listado, un
array con los resultados, con todos los errores.
Como ven tienen un ejemplo. En este caso es el método register. Lo primero que
hace, es guardar ese resultado en una variable (errors) y luego pregunta si es que
errors.isEmpty() (está vacío), que es otro método de validación que está dentro de
Express-validator. Si es que está vacío, es decir si no hay errores, que me agregue
el objeto nuevo con el usuario, que escriba el JSON y que me redireccione a la vista
del perfil del usuario, por ejemplo. Esto es si no hay errores.

Pero si es que hay errores, vamos a volver al formulario y decirle: Che, las
credenciales no están bien o la contraseña está mal. Bueno, no se recomienda eso
en realidad, porque bueno eso puede ser alguien malicioso que intente Ingresar a tu
perfil y si nosotros le decimos el usuario está mal, bueno, va a probar con otro
usuario, hasta que le pegue a uno. Pero si le decimos el password está mal, va a
empezar a probar con todas las combinaciones posibles hasta que lo pueda romper
a la encriptación del código, de la contraseña. Así que hay que tener ojo ahí, en este
caso en específico de registro de logueo, con el tema de cómo mostramos lo que
está bien o mal. Ahí podemos ir mostrando de forma descriptiva, cuáles son los
errores.
El método maped()

Yo les mencionaba que era un array. Es decir, para que podamos manipularlo,
íbamos a tener que hacer un foreach por ejemplo, y luego íbamos a poder ir
imprimiendo esos errores.

El objeto de errores

Pero con el maped, lo que podemos hacer es acceder a los errores de email y al
mensaje, a los errores de password y al mensaje. Y acá se ve el value que puso y
demás. Hay que tener ojo también con eso. Pero la ventaja de eso, es que podemos
manipular el valor anterior que puso, la información anterior y demás.

Mostrando los errores en la vista

Y el último paso, porque acá ya prácticamente lo enviamos mapeado al error,

Mandamos algo que dice old. ¿Qué sería ese old? Hablando siempre del caso en
que el usuario se quiera registrar y tenga algún error en el formulario. Le devuelve
los datos, justamente porque puede haber datos que si estaban bien y esos datos
necesitamos que sigan estando, porque si no se vuelve tedioso. No sé si les pasó a
ustedes que intentaron registrarse en alguna página o ingresar alguna página y si se
equivocaban y le dejaban todos los campos del formulario en blanco y les tocaba de
nuevo hacerlo a mano, cargar todo y es super tedioso. La idea es que ya les
dejemos precargado todo lo que está bien y solamente cambiemos los valores de lo
que está mal. Me refiero a la información que venía antes en el formulario. Y
simplemente, para mostrar los errores, vamos a agregar un condicional preguntando
si es que existen errores y si hay algún error con el nombre name. Si es que
coinciden o si son true las dos cosas, vamos a crear una <p> que nos muestre el
nombre del error.
En este caso, creo que debería ser errors.msg, para que nos salga: debes
completar un email válido. Ya lo vamos a probar.

Y acá recuerden también que debemos agregar los datos anteriores. Si es que
venían datos correctos acá, le damos locals.old, y si venía la propiedad de email,
lo agregamos nuevamente, para que no molestemos al usuario.

¿Todo esto que hemos visto en la segunda parte, esta dentro del controlador?
Sí, desde el controlador, hasta el paso donde lo enviamos a ejs. La ventaja de
hacerlo con el maped, es que podemos agregar mensajes personalizados, en cada
uno de los espacios donde queremos. Porque si nosotros usamos sin mapear, nos
va a llegar un array y en ese array tendríamos que hacer un foreach en alguna
cajita de alguna parte de la pantalla.

Y otra preguntita. porque he visto en el material como divididas las opiniones


o parece por lo menos que algunos Usan el check y otros el body.

Funciona exactamente igual. Debe tener alguna condición ahí. Aparentemente, el


check se usa más cuando usamos queries. Yo lo probé para los post los probé con
Body y con check y funcionaban igual, así que no habría problema con eso.

Continuemos con el proyecto y le agregamos validaciones a los formularios.

Validaciones en el CRUD2
Me voy a la carpetita de nuestra comisión, vamos a hacer en la 29 que estaba el
CRUD2. Voy a crear una carpeta nueva que se llame clase 31, middlewares y
vamos a copiar lo que tenía la 29. Vamos a sacar estos nodes_modules que me
están ocupando espacio. Arranquemos con esto. Tenemos el proyecto continuado
de lo que era el crud. ¿Qué opinan si empezamos ahí. Teníamos ya configurado
nuestro package.json, con todas las cosas que venían en Express validator, que
había cosas que ni sabíamos para qué servían, pero están ahí.
Empecemos agregando un middlewares de forma global. Que nos vaya haciendo
un log, que nos vaya diciendo: Tal usuario entró en tal lugar, a tal hora. ¿Les parece
como para tener algo extra? Ya teníamos el middlewares de
middlewares/multer.js,
Que configuraba dónde se guardaba,

cómo se iba a llamar

y qué archivos recibía, en este caso recibía solamente imágenes, de tipo imagen.
Y lo exportamos para poder utilizarlo, obviamente porque es un middlewares.

Creamos un middleware global de rastreo de usuario (logs.js)

Vamos a crear otro middlewares para seguir con el ejemplo que estaba en la
grabación. Ahora vamos a hacer un middlewares de forma global, que va a tener
como objetivo que cada vez que un usuario entre a nuestra aplicación, a nuestra
página, vaya guardando por dónde va. Esto a veces está bueno para ir haciendo un
análisis de Mercado y decir: Bueno, a x cantidad de personas le interesa más entrar
por el lado de las vistas de las zapatillas de tal categoría, por ejemplo. Algo así se
usa, algo así sería la lógica. Vamos a empezar. En este caso, quiero ir guardando
eso, vamos a crear una función que en este caso va a tener el req el res y el next.

Dos formas de exportar la función

Como a esto voy a exportarlo, simplemente voy a hacer una función anónima:

module.exports = function (req, res, next) {

Esa sería una opción. La otra opción, sería como lo veníamos haciendo.
function logs(req, res, next) {

}
module.exports = logs

Para no estar haciendo eso abajo, directamente exporto la función, es exactamente


lo mismo. Es para mostrarles que se puede hacer de esta forma también, sin
necesidad de ponerle un nombre, porque después esto lo importamos y lo vamos a
importar con ese nombre o con el que queramos, milanesa, o lo que sea. Vamos a
generar un mensaje y ese mensaje va a ser una concatenación de: “el usuario
ingresó ingresó en la URL:” y acá vamos a utilizar lo que venga del request URL
(req.url). Y le vamos a poner que a las xx:xx hs, porque todavía no sé cómo usarlo
a esto.

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`

}
Creamos logs.txt en la carpeta data

¿Qué más necesitamos? Necesitamos un lugar en donde guardar este mensaje. Así
que vamos a crear acá un archivo en Data, que le llamaremos logs.txt, va a ser de
texto.

Requerimos writeFileSync

¿Qué más necesitamos? Necesitamos usar un módulo para escribir ese logs.txt.
Con fs y vamos a usar el writeFileSync. Pero como simplemente voy a usar el
writeFileSync, no me quiero traer todo el fs. Así que vamos a hacer destructuring.
Estamos destructurando o obteniendo solamente el método writeFileSync, de todo
lo que es el objeto con distintos métodos que es fs. Así que simplemente vamos a
traernos writeFileSync. La idea de eso es para que no esté haciendo
fs.writeFileSync a cada rato, simplemente y también para no traerme todo, porque
ahora simplemente estoy leyendo writeFileSync de todo de lo que es el objeto.

const { writeFileSync } = require('fs')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
}
writeFileSync necesitaba dos parámetros: el primer parámetro, como nos indica ahí
en celeste, azul, es la ruta.

Requerimos path

Vamos a usar path. Vamos a ver si me da la opción de requerirlo.

Cuando le salga ese simbolito y presionamos Tab, podemos requerirlo


(automáticamente).
Ahí se hizo el require de forma automática.

const { writeFileSync } = require('fs')


const path = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(path)
}

Requerimos join

y de path vamos a usar join. Así que podemos hacer el destructuring, ya que
estamos.

const { writeFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(path)
}
Simplemente vamos a usar join de path.

const { writeFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join)
}

Y path nos servía para unir todos los argumentos. y los normaliza. Vamos a unir
dirname, en este caso dónde estamos parados? En logs. Me parece que tenemos
que volver una para atrás: entramos a Data y luego a logs.txt. ¿Estamos bien con
la ruta?

const { writeFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join(__dirname, '../data/logs.txt'))

}
Podríamos hacer el uso de otro método que se llamaba existsSync(), que
preguntaba si es que existe. Pero vamos a dejarlo Ahí vamos a jugar a la suerte de
que ya teníamos un logs.txt.

================================================================
=================

El método existssync() es una función en Node.js que se utiliza para verificar si un archivo o
directorio existe de forma síncrona. Devuelve true si el archivo o directorio existe y false si no
existe.

Aquí tienes un ejemplo de cómo usar existssync() en Node.js:

const fs = require('fs');

if (fs.existsSync('/path/to/file')) {

console.log('El archivo existe');

} else {

console.log('El archivo no existe');

================================================================
=================

Usamos appendFilSync en vez de writeFileSync

Y en este caso vamos a usar appendFilSync en lugar de writeFileSync, que lo


tengo que traer de fs.

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join(__dirname, '../data/logs.txt'))

}
Entonces vamos a usar solamente appendFilSync porque queremos que, a medida
que vayan ingresando a todas las páginas, se vaya agregando el contenido y no que
se vaya eliminando.

Acá hay algo más que me gustaría hacer y es un salto de línea. No me acuerdo
cómo era el símbolo, así que simplemente lo voy a hacer con este tipo de
concatenación que me gusta usar a mí.

Creo que era \n, sí pero no me acuerdo si era invertida la barra creo.

¿Ya exportamos esto?

Requerimos logs.js en app.js (de forma global)

Ya lo tenemos exportado, así que tranquilamente lo podemos importar. Como va a


ser un middlewares de forma global, quiero que se vaya ejecutando en todas las
rutas, lo vamos a meter en app.js. En el require le indicamos la ruta donde está,
tenemos que Ingresar a Data simplemente, porque nuestro app.js está a la misma
altura de la carpeta Data. Así que decimos que lo que queremos obtener es logs.

// ************ Require's ************


const createError = require('http-errors');
const cookieParser = require('cookie-parser');
const express = require('express');
const logger = require('morgan');
const path = require('path');
const methodOverride = require('method-override'); // Pasar poder
usar los métodos PUT y DELETE
const logs = require('./data/logs.js')

Agregamos el middlewares logs en app.js

Y luego lo tenemos que utilizar acá. otro middlewares, que se llama en este caso
logs.

// ************ Require's ************


const createError = require('http-errors');
const cookieParser = require('cookie-parser');
const express = require('express');
const logger = require('morgan');
const path = require('path');
const methodOverride = require('method-override'); // Pasar poder
usar los métodos PUT y DELETE
const logs = require('./data/logs.js')
// ************ express() - (don't touch) ************
const app = express();

// ************ Middlewares - (don't touch) ************


app.use(express.static(path.join(__dirname, '../public'))); //
Necesario para los archivos estáticos en el folder /public
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(logger('dev'));
app.use(cookieParser());
app.use(methodOverride('_method')); // Para poder pisar el
method="POST" en el formulario por PUT y DELETE
app.use(logs)

// ************ Template Engine - (don't touch) ************


app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '/views')); // Define la
ubicación de la carpeta de las Vistas

Probamos el middlewares

¿Y ahora cómo lo probamos a esto?

Así que le damos a npm run dev. Y me dice que no me encuentra el módulo.

Puse mal la ruta puede ser? En los lugares donde se lo está requiriendo,
Aparentemente es acá:

¿Pero dónde lo estamos usando? En App, línea 8 dice.


Cambiamos data por middlewares en app.js

Veamos el app línea 8 y veamos si coincide con lo nuestro. ¿Está bien esto?

¿Se llama logs? ¿Qué estoy intentando requerir? Estaba intentando acceder a data
y está en middlewares.

Cambio data por middlewares.

// ************ Require's ************


const createError = require('http-errors');
const cookieParser = require('cookie-parser');
const express = require('express');
const logger = require('morgan');
const path = require('path');
const methodOverride = require('method-override'); // Pasar poder
usar los métodos PUT y DELETE
const logs = require('./middlewares/logs.js')
// ************ express() - (don't touch) ************
const app = express();
// ************ Middlewares - (don't touch) ************
app.use(express.static(path.join(__dirname, '../public'))); //
Necesario para los archivos estáticos en el folder /public
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(logger('dev'));
app.use(cookieParser());
app.use(methodOverride('_method')); // Para poder pisar el
method="POST" en el formulario por PUT y DELETE
app.use(logs)

// ************ Template Engine - (don't touch) ************


app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '/views')); // Define la
ubicación de la carpeta de las Vistas
// ************ WRITE YOUR CODE FROM HERE ************
// ************ Route System require and use() ************
const mainRouter = require('./routes/main'); // Rutas main
const productsRouter = require('./routes/products'); // Rutas
/products

app.use('/', mainRouter);
app.use('/products', productsRouter);

// ************ DON'T TOUCH FROM HERE ************


// ************ catch 404 and forward to error handler
************
app.use((req, res, next) => next(createError(404)));

// ************ error handler ************


app.use((err, req, res, next) => {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.path = req.path;
res.locals.error = req.app.get('env') === 'development' ? err :
{};

// render the error page


res.status(err.status || 500);
res.render('error');
});

// ************ exports app - dont'touch ************


module.exports = app;
Agregamos next en el middlewares

Bueno ahí ya va cambiando un poco el error, pero acá me dice app.js línea 20.

Me parece que está bien.

Me estaba faltando el next para que continúe después.

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join(__dirname, '../data/logs.txt'))
next()
}

Agregamos el segundo parámetro a appendFileSync

Y nos falta la s en el export. Y acá también tenemos un error en el


appendFileSync, recuerden que el primer parámetro es la ruta, y el segundo
parámetro es la información que queremos que se agregue. En este caso no tiene
nada como para que se agregue. Así que nos falta el segundo parámetro que es el
mensaje ese que creamos arriba.

const { appendFileSync } = require('fs')


const {join} = require('path')
module.exports = function (req, res, next) {
let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join(__dirname, '../data/logs.txt'), msg)
next()

Probamos nuevamente el middlewares

Vamos a localhost:3000. Recuerden que cada vez que yo hago un pedido a


cualquier ruta, se me debería ir escribiendo en nuestro logs. Bueno, ingresemos a
localhost:3000/products/create. Ingresemos a listado de productos
localhost:3000/products y volvamos a ver qué pasó en el logs. Miren: funciona.

Agregamos time.getHours y time.getMinutes

Nos falta lo nuevo, que yo les comentaba que íbamos a agregar algo extra

Y va a ser manipular la hora y los minutos en lo que se está ejecutando.


Vamos a crear una constante que le podemos llamar time o now, el tiempo en este
momento, y eso se genera con new Date(). Esto es javascript, no es nada instalado.

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


const time = new Date()
let msg = `El usuario ingresó en la URL: ${req.url} a las
xx:xxhs`
writeFileSync(join(__dirname, '../data/logs.txt'), msg)
next()

Y esto nos va a traer muchísimas cosas. Va a ser un objeto con muchos métodos,
dentro de los cuales van a tener por ejemplo get year, get hours, pueden traer
minutos, segundos, lo que ustedes quieran. En este caso, a mí me interesa la hora y
los minutos.

Así que vamos a usar símbolo peso llave(${ }) para agregar una variable nueva. Le
vamos a llamar time.getHours (obtener horas). Y el siguiente va a ser
time.getMinutes. (Obtener minutos).

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


const time = new Date()
let msg = `El usuario ingresó en la URL: ${req.url} a las
${time.getHours}:${time.getMinutes}hs`
writeFileSync(join(__dirname, '../data/logs.txt'), msg)
next()

Y me falta ejecutar la función para que me devuelva los minutos efectivamente.


Vamos nuevamente a probar la página. así que bueno vamos ahora a
localhost:3000/milanesa/detail.

Me dice que no existe, obviamente. Y en el logs como ven dice el usuario ingresó
o intentó ingresar en la URL milanesa detail a las 15:29 horas.
Este es el middlewares que creamos.

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


const time = new Date()
let msg = `El usuario ingresó en la URL: ${req.url} a las
${time.getHours}:${time.getMinutes}hs`
writeFileSync(join(__dirname, '../data/logs.txt'), msg)
next()

El objetivo de este middlewares es que cada vez que un usuario ingrese a una
página, me vaya guardando en algún archivo de texto, adónde ingresó. En este
caso el middlewares es Global, al ser global ya no hace falta que lo metamos en
cada ruta.
Esto ya funciona en todas partes. Hice el require en la línea 8, y en la línea 20 lo
metí al logs. Podríamos hacerlo más complejo y obtener el nombre del usuario y
que el usuario es tal, que ingresó a tal página a tal hora, ir guardando un logs por
usuario o ir haciendo lo que lo que se imaginen.

Creo que el date lo podemos guardar de otra forma.

const { appendFileSync } = require('fs')


const {join} = require('path')

module.exports = function (req, res, next) {


const time = new Date()
const minutes = time.getMinutes()
const hours = time.getHours()

let msg = `El usuario ingresó en la URL: ${req.url} a las


${hours}:${minutes}hs`
writeFileSync(join(__dirname, '../data/logs.txt'), msg)
next()

}
Ahí queda un poquito mejor el mensaje. Pero arriba estamos haciendo el guardado
de cada uno de los valores. Esto es prácticamente lo mismo que estaba en
playground.

Agregamos Express-validator al proyecto

Ahora vamos a lo más importante de la clase de hoy que sería justamente agregar
Express-validator.

Abro otra terminal y vamos a instalar express-validator.

Algo que vi también ahí que no me gustó, que ya viene preconfigurado en


express-generator es que nodemon viene instalado como dependencia global o
de producción yo les mencionaba que esa es una dependencia de desarrollo, así
que lo vamos a desinstalar.

También como para que vean que se pueden eliminar librerías si nos equivocamos,
podemos desinstalar de esa forma, y luego le instalamos de nuevo.
Info extra como para que puedan ver que se pueden instalar cosas, desinstalar
cosas, instalar como dependencia o desarrollo, como ustedes quieran.

Profe, no escuché en este caso, por qué convenía desinstalarlo.


Porque nosotros cuando lo usamos, o sea cuando el proyecto esté listo para producción
vamos a usar este comando:

Y este,

solamente lo usamos cuando estamos de forma local, en desarrollo.


Así que eso debería ser una dependencia de desarrollo.

Pero ¿Se lo desinstala o se lo deja de usar no más?

No, no habría problema ahí como está ya no habría drama, porque para que
funcione el proyecto, va a instalar todo ahí. Cuando ya nos vamos a producción, a
esto

lo deja de lado.

Recordemos que acabamos de instalar Express-validator


Ya tenemos los formularios creación de productos product-create-form.ejs

y el de edición de productos product-edit-form.ejs.

Prácticamente tienen lo mismo, así que nos puede servir para los dos formularios.
Vamos a crear un middlewares nuevo que se llame validateProducts.js.

porque nos va a servir para hacer la validación. Y vamos a empezar a traernos todo
lo que necesitamos validar. Voy a traerme Body de express-validator. Y ahí vamos
a empezar a armar este objeto, haciendo lo mismo de hace rato: module.exports
igual a un array, y acá va a tener lo que sea del campo nombre, lo que sea del
campo precio y demás.

validateProduct.js
const { body } = require('express-validator')

module.exports = [

Como no me acuerdo el nombre de cada cosa, voy a abrir una nueva ventanita acá
con el formulario para que vaya viendo.

Y ya que estamos con visual Studio, vamos a usar la lupita para que me ayude a
buscar las cosas. Vamos a poner que todos los name me los deje como
sombreados, para que me vaya ayudando a identificar.
El primero es name. Con el método Body, vamos a validar lo que contenga name.
¿qué podemos validar del nombre del producto?

Que no sea vacío.

Usamos .notEmpty. y le podemos hacer un mensaje. withMessage(‘debes ingresar


un nombre’) Y ahí podemos hacer un .bail también, como para que diga: si hay
error, quédate ahí.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()

¿Qué más puede ser? El input de tipo name es un texto, así que podríamos decir:
Que sea alfanumérico. Miren que acá tiene un montón de validaciones.
Y creamos un mensaje nuevo Debe ser un un texto.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()
.isAlphanumeric().withMessage('Debe ser un texto'),
]

Del input price.

Que no esté vacío. y que tenga el mensaje Ingresa un precio. y acá podemos
hacer un .bail, como para decir que se corte si es que llegó el primer error y si no
que siga.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()
.isAlphanumeric().withMessage('Debe ser un texto'),
body('price')
.notEmpty().withMessage('Ingresa un precio').bail()

Que sea numérico. y que tenga el mensaje El precio debe ser un número.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()
.isAlphanumeric().withMessage('Debe ser un texto'),
body('price')
.notEmpty().withMessage('Ingresa un precio').bail()
.isNumeric().withMessage('El precio debe ser un numero'),
body('description')

Del input descripción.

Que no esté vacío. y que tenga el mensaje Ingresa una descripción.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()
.isAlphanumeric().withMessage('Debe ser un texto'),
body('price')
.notEmpty().withMessage('Ingresa un precio').bail()
body('description')
.notEmpty().withMessage('Ingresa una descripción'),

Profe, el del precio, por ejemplo, ¿Le debería poner que solamente sea
numérico?
Sí estaría bueno que sea numérico también.
O sea, ¿desde el html se puede bloquear eso? Pero si uno lo cambia a texto
editándolo, ¿Igual ingresaría?
Claro. Ese es el problema de usar formulario o usar una validación en el html,
porque por ejemplo si nosotros acá tenemos un descuento, creo que
descuento debería ser numérico y es texto esto, debería ser un
número.
Y el precio del producto también debería ser un número,

pero está con un input de tipo texto. Eso está mal. Pero supongamos que lo
tenemos como número, tranquilamente el usuario puede decir: Yo quiero
romper esto, y a este input, en vez de que sea de texto, quiero que sea
number.
Y ahí cuando intento poner una letra, no me deja, solamente son números.

Y si le da enviar, nos va a enviar esta información así de esta form.


Es más, algo que no les había mostrado en esta comi, todavía era de que hay
que tener ojo con dejar el spread operator en la creación de productos,
porque en este caso, este input es de nombre price.

Pero podemos hacer uno que se llame access o algo así, que tenga alguna
cosa encriptada o algo

y puede llegar a mandar información en el body que nos abra alguna puerta,
que nos robe información o que nos genere algún problema con la aplicación.
Así que hay que tener ojo ahí con esas cosas. Ya lo vamos a corregir.

Profe ¿tiene que ser decimal el precio también?


Puede ser. si es que lo tenemos configurado así, puede ser. Agreguemos
isNumeric, que sea
numérico, y le agregamos un mensaje withMessage(El precio debe ser un
número)
Creo que esto va a generar un error en base a como lo tenemos, porque
estamos recibiendo un texto. Y acá podemos hacer un .bail, como para decir
que se corte si es que llegó al primer error y si no, que siga.

validateProduct.js
const { body } = require('express-validator')

module.exports = [
body('name')
.notEmpty().withMessage('Debes ingresar un nombre').bail()
.isAlphanumeric().withMessage('Debe ser un texto'),
body('price')
.notEmpty().withMessage('Ingresa un precio').bail()
.isNumeric().withMessage('El precio debe ser un número'),
body('description')
.notEmpty().withMessage('Ingresa una descripción'),

Profe, ¿Hay que cambiar el formulario el tipo de dato?


Habría que cambiarlo, si. Vamos a cambiarlo ya que estamos. Lo tenemos por
acá. ¿Dónde está el de precio?

veamos que haya quedado bien


Ahí sí quedó bien porque ya no me deja escribir. Se pueden seguir haciendo todas
las que nosotros queramos, pero para no perder tiempo con esto, lo dejo hasta acá.
Validaciones quedan hasta aquí. Recuerden que tienen un montón para agregar.
Cuantas más agreguen mejor, para evitar esas posibles roturas de nuestra
aplicación. Paso dos Listo. ya tenemos lo que queremos validar.

Paso tres:

Nos vamos a nuestra ruta, donde lo vamos a usar, que en nuestro caso sería en
routes/products y requerimos este middlewares.

validateProduct = require(‘../middlewares/validateProducts’)

Y lo guardamos en validateProduct. Le indicamos la ruta, que en este caso


tenemos que volver uno hacia atrás, ingresar a middlewares e ingresar a
validateProducts.

routes/product.js
// ************ Require's ************
const express = require('express');
const router = express.Router();

// multer middleware
const upload = require('../middlewares/multer')
// validations middleware
const validateProducts =
require('../middlewares/validateProducts')
// ************ Controller Require ************
const productsController =
require('../controllers/productsController');

/*** GET ALL PRODUCTS http://localhost:3000/products ***/


router.get('/', productsController.index);

/*** GET ONE PRODUCT http://localhost:3000/products/detail/1 ***/


router.get('/detail/:id', productsController.detail);

/*** CREATE ONE PRODUCT http://localhost:3000/products/create ***/


router.get('/create', productsController.create);
router.post('/create', upload.single('image'),validateProducts,
productsController.store);

/*** EDIT ONE PRODUCT http://localhost:3000/products/edit/1 ***/


router.get('/edit/:id', productsController.edit);
router.put('/edit/:id', upload.single('image'),
productsController.update);

/*** DELETE ONE PRODUCT***/


router.delete('/delete/:id', productsController.destroy);

module.exports = router;

Y agrego el middlewares validateProducts en la ruta del create, que utiliza un


método de tipo POST, que es donde lo vamos a probar primero. La idea es que en
cuando el cliente apunte a /create, configuramos que lo reciba el método store de
productsController, pero antes de eso, se deberá procesar la imagen y validar los campos
del formulario a través de validateProducts.js.
Hacemos un paréntesis: La ruta, en este caso, va de esta forma: el primero va a ser
la ruta, el segundo va a ser el middlewares de procesamiento de la imagen (el
multer), el tercero un middlewares de validación de productos, y el cuarto es el
controlador que nos hace el guardado del producto.

router.put('/edit/:id', upload.single('image'),
productsController.update);

Eso lo hicimos hace dos clases,

que lo que hace es generar un ID único, se fija si la imagen existe o si viene una
imagen y si no le pone por default, agrega con req.body lo que viene en el body, que
ahí está lo que yo les decía que es peligroso, porque acá estoy dejando oportunidad
que la gente inyecte más información. Puede inyectar cuantas cosas quieran en el
body.

Profe ¿Hasta Cuántos middlewares se pueden agregar? Lo que ustedes quieran.


No hay problema con eso, siempre y cuando no se olviden de agregar el next para
que pueda continuar con la pila de ejecución. Y la ventaja es que no tenemos toda
la lógica dentro del middlewares de procesamiento de la imagen.Porque si no
tendríamos que hacer ahí el el callback con el req el res y el next. Por eso, cada
uno tiene su responsabilidad.
El middlewares validateProduct.js valida los campos del formulario.

El middlewares multer.js me crea la imagen con un nombre específico y me filtra


por imágenes en este caso.
Y después logs.js es uno global, qué lo que hace es realizar un seguimiento de los
usuarios registrando la hora y los minutos en los que por ejemplo ingresan a una
sección de la página.

Ya tenemos listo lo que es el validateProduct.js. Ahora nos queda probarlo. ¿Cómo


sabemos si va a funcionar? Todavía no sabemos.

Ahora nos falta el

quinto paso.

Sigamos la ruta: Cuando el usuario apunta a /create, es decir cuando hace click en
el botón del formulario de enviar, primero actúa el primer middlewares, guarda la
imagen, siempre y cuando sea una imagen, luego a través de validateProducts se
fija si es que hay errores o si todos los campos están bien. En caso de que estén
bien, se guardan en alguna parte de este middlewares, pero todavía no hace nada
acá en el store. Ahora tenemos que ir al store que está en
controllers/productsController.js, para ver si podemos obtener esa información
que se va guardando.
Hasta el momento teníamos solamente esto, creamos el nuevo objeto,

Pushamos el nuevo objeto.


Agregábamos el nuevo producto al JSON.

Ahora voy a preguntar primero: Si es que no hay errores, haceme todo esto. Si es
que hay, hace otra cosa. Primero vamos a intentar ver qué nos trae errors.
Así que error va a tener lo que nos trae validationResult. Les mencionaba que
visual studio hizo el Salto de línea solo cuando yo puse validationResult y le metí
un Tab y me auto importó en la línea 1,

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

que es justamente lo que vamos a necesitar de multer, que es validationResult.

Y lo que vamos a validar del resultado, sería lo que viene del request. Así que le
vamos a indicar que lo que venga del request, me lo guarden es errors.

Vamos a empezar haciendo unos console.log.

Al primer console.log le vamos a llamar errors. Y quiero que me muestre los datos
en bruto.

Vamos a hacer una Barrita como de separación y veamos qué pasa con errors
maped, que es un método que viene incluido en express-validator.
Simplemente estoy haciendo console.log para ver cuál es la diferencia entre errors
y errors mapped.

El proyecto creo que estaba levantado.

Vamos al formulario y vamos a enviarlo vacío.

A ver qué pasa. Aparentemente me creó un producto sin nada.


Eso no está bien. No estaría bueno que el administrador de la página cree
productos vacíos. Miren lo que pasó acá. ya tengo los dos console.log.

El primer console.log, que se llamaba errors, me trae Result, luego me trae un


array (errors) dentro, y en el array me trae todos los campos. Trae name, price, y
description. Pero lo noto un poquito molesto para manipularlo, ya que para mostrar
los errores en pantalla, lo que tendríamos que hacer es un for each errors y que me
imprima los mensajes. Pero hay que ver que esté bien el orden y es como que ya es
más complicado.

Y luego con el maped, miren de Iindo que queda. Un objeto con input name, input
price, input description, de esa forma es mucho más sencillo utilizarlo.
Directamente invoco el nombre.msj, por ejemplo. Es más fácil manipularlo de forma
individual.

Me parece que nos quedamos con el mapped. o quieren que empecemos a hacer
con el errors y después lo pasamos a mapped para quede más lindo. Usemos el
errors primero como para que vean.

Ahora preguntemos: ¿Hay errores? ¿errors está vacío? Si es que está vacío, o sea
si no hay errores, haceme todo eso que ya estabas haciendo. Y si no, mandame de
nuevo el formulario y mostrame el error. O sea, hacemos un res.render de la vista,
de product-create-form.ejs. y mándame un objeto con errors y le llamamos
errors, que en este caso va a ser errors solamente. Y mandame también la
información vieja, que lo vamos a llamar oldData y eso va a ser todo lo que venía
en el body antes.

Vamos ahora al formulario. Vamos a hacer un div para atrapar los errores. Vamos a
hacer un forEach de ese array con errores, y a cada elemento le voy a llamar
error, y cada vez que pase por un error, que me imprima una <p> que me muestre
ese mensaje. Vamos a hacer ejs output de error.msg.
Y creo que esto no va a funcionar, porque creo que no estoy enviando bien el objeto
porque Result es un objeto y adentro tiene errors.

Probemos. Volvamos al formulario de creación,


Ahí nos dice que errors is not defined. Y eso porque puede ser que todavía no
exista ningún error, así que primero preguntemos si existen errores usamos un ejs If

Y si es que existe errors, que haga ese forEeach.

Veamos ahí si se soluciona el error.


Por lo menos la vista está. Si le damos a guardar producto, me sale un error de
sintaxis: errors.forEach is not a function.

Me parece que es lo que yo les decía. El objeto que vamos a mandar, no es errors
solo, porque errors solo es un objeto,
sino que sería errors.errors.

¿Les parece que lo llamemos de otra forma a este error? ¿Si le llamamos results
para que tenga más sentido? O sea que el validationResult nos va a traer una
variable que le llamamos results, y dentro de las cuales así en crudo, nos trae un
objeto results que tiene varias cosas, y en las cuales nosotros necesitamos el array
errors.

Veamos ahí si funciona. Le damos guardar producto en el formulario y de forma muy


pequeña me dice: debes ingresar un nombre, un precio y demás.

Pero no queda muy bonita a la vista. Quizás le podríamos dar estilo, que ese errors
sea una caja que esté oculta, y que cuando se genere el error me haga pop up una
ventanita flotante, que tape toda la pantalla y que ahí me muestre el error o algo así,
pero no es de mi agrado.

Esta era una forma, enviar errors, la otra opción era enviarlo results.mapped.

Y en el caso del formulario, lo que habíamos agregado, que no lo vamos a usar, es


este bloque de código.
Veamos si no afecta en nada que lo comentemos. Ya está listo. Enviamos
results.mapped() desde controllers/producstController.js, con el nombre de
errors.

y ahora podemos acceder a errors.name por ejemplo,


para manejar todo lo que son sus propiedades, puedo manejar errors.price para
enviar el msj “Ingresa un precio” y demás.

Vamos nuevamente a views/product-create-form.ejs, y vamos a trabajar en cada


uno de los inputs. Arranquemos por el primero. Agregamos un ejsIf,

Y pregunto si existen errores (locals.errors) y también existen errores de nombre


(errors.name), o sea si las dos cosas coinciden, imprime una <p> usando
ejsOutput y que diga errors.name.msj.

Porque en este caso queremos mostrar solamente el mensaje. Y vamos viendo si


funciona.
Da errors.forEach in not a function. Aparentemente no me deja hacer
comentarios acá.

Qué raro, ¿será por la sintaxis? Lamentablemente se va este bloque de código con
el forEach. Así no perdamos tiempo con eso. Ahí tenemos el formulario andando.
Mando el formulario vacío, y ya efectivamente me sale el mensaje Debes ingresar
un nombre.
Obviamente le tenemos que dar estilo, ponerle que sea colorcito rojo que se alinee
hacia un lado, etc. Pero ya tenemos nuestro input específico para detectar el error o
que me vaya mostrando. Completo el nombre del producto en el formulario, y
cuando envío efectivamente ya se fue el error.

Pero no me dejó crear el producto, porque siguen habiendo errores. Y algo que me
estoy olvidando, es agregarle a cada input el valor anterior. ¿En qué lugar va
precargada la información que ya tenía en cada input? En el value de cada uno de
los input, y viene desde el body. Por ejemplo en este input que era el de name,
vamos a agregarle un ejsOutput

Y vamos a hacer un condicional, en este caso va a ser un ternario. Y preguntamos


si es que viene información vieja (oldData) (le habíamos llamado), y también si en
ese body en la primera vez le cargamos información al por ejemplo input name
(nombre) (oldData.name), signo de pregunta (?) y que me imprima ese valor
oldData.name. Y si no (:) que me imprima un null. Acá estamos haciendo un if
ternario preguntando si es que venía info antes y también en esa info antes venía
un valor que es name, imprimime ese nombre y si no déjalo vacío.
Pongamos milanesa, hacemos clic en Guardar producto,

y como ven sigue persistiendo este valor. Así que ahí tenemos funcionando eso.
Obviamente me faltan agregar todos los demás campos, pero eso lo van a hacer
ustedes.

Está bueno así como está esta estructura, porque miren tienen cada input en
específico un div, como para el input name. Luego tienen otro div que es específico
para el precio y demás. Veamos si sigue funcionando. Ahora vamos a crear un
producto nuevo que se llame aerógrafo. El precio va a ser ser 100,000
supongamos, el descuento va a ser de 5%, la categoría va a ser en oferta y la
descripción. La imagen no tengo. Se crea efectivamente el aerógrafo con todas las
cositas.
Ahí tenemos funcionando nuestra validación. Como ven, el errors de los dos
console.log me salen vacíos.

Porque en la última instancia, no había errores. Tranquilamente podemos comentar


o eliminar o hacer lo que queramos con estos console.log.

Les dejo los console.log para que lo tengan ahí, y puedan revisar las cosas. Está
buenísimo que se acostumbren a usar console.log. una vez que ya no los
necesiten o lo comentan o lo eliminan lo ideal sería que lo eliminen. Hasta que se
vayan acostumbrando a consultar información, está bueno usarlo y agregarle
quizás mensajitos así, como para saber identificar cuál es uno y cuál es otro,
cuando tengamos que comparar cosas muy parecidas. O quizás podemos agregarle
un String que diga prueba de tal cosa, y a la par le pones lo que queres probar. Y
te sirve como para identificar dónde está ese console.log, porque a veces si lo
dejamos suelto no uno no sabe de dónde viene eso.

Veamos si funciona el delete.

Vamos a hacer un delete. Me dice que no encuentra el directorio para eliminarlo.

¿Esto les había mostrado? ¿Se acuerdan que estaba el fs unlink, que servía para
eliminar imágenes? Ahora intenté ejecutar este método (destroy)

y me tiró el error en el unlinkSync.


Ven y me dice que bueno que no encuentra el directorio para eliminarlo. ¿Vimos el
unlinkSync para qué servía? En el destroy lo que hacíamos era separar ese
producto de que queríamos eliminar y lo volvíamos a escribir al JSON sin ese
producto. Luego agregamos fs.unlinkSync para poder borrar la imagen, porque si
no nos quedarían muchas imágenes sueltas de productos que ya eliminamos. Acá
Tengo dos problemas: un problema es que está mal la ruta:

Y el otro problema es que lo que estaba intentando hacer es borrar la imagen por
default (default-image.png). Y eso está mal. Si borro la imagen por default, todos
los demás productos que no tienen imagen y estaban usando eso van a aparecer
sin imagen. Acá tendría que preguntar primero si la imagen no es
default-image.png, eliminame la imagen, si no, no.

Si la imagen a ver de todo esto punto join

si productToDelete.image es diferente default-image.png, que la elimine. Igual


está mal la ruta.

Veamos el error.Está ingresando a images y no está entrando al directorio product.


Lo que hace path.join es imprimirme el directorio donde está parado (__dirname),
en este caso sería src/controllers, y luego hace un ../ para volverse hasta src,
luego hace otro ../ para volverse hasta C31-middlewares, luego ingresa al directorio
public, ingresa al directorio image, y luego ingresa al directorio products. Y luego
ingresa al nombre de la imagen para que podamos obtener obviamente esa ruta
absoluta.

Veamos algún producto en específico que queramos eliminar. Este no tiene imagen.

Presionamos en el botón Eliminar. Se va a eliminar el producto, pero no se debería


eliminar la imagen. Ahí está. Y supongamos que ahora sí queremos eliminar uno
con imagen.
Recordemos el nombre de la imagen. Vamos a inspeccionar y a ver cómo se
llamaba la imagen.

Si funciona bien esto, se debería eliminar.

Le dimos a delete. Y ya no aparece el producto en el listado de productos. La


buscamos en public/images/products/image y ya no esta
Así que el fs.unlinkSync está funcionando perfecto. El concepto es que si borro el
producto del listado, tengo que borrar la imagen de ese producto en la carpeta
products. Porque si no, vamos a borrar el producto en el listado JSON, pero la
imagen va a seguir guardada en public, y vamos a tener un montón de imágenes
que no se van a usar. Ahí ya está a prueba de fallas.

**************************************
La primera Consigna es hacer exactamente lo mismo que hicimos hace un
momento, lo del middleware de forma global. Y después el otro, va a ser
manipulando la query.params, o un query String en realidad, para que pregunte si
es que viene un administrador, que me muestre la vista y si no, no. Ese deberían
agregarlo en determinada ruta para ver si me deja entrar. ¿Se anima uno a
compartir la pantalla y lo intentamos resolver? No se olviden revisar todo la
estructura del proyecto, si que tiene instaladas las cosas, si el package.Json está
bien, todo eso revisen.

En el package podrías ya agregar lo del lo del dev para tenerlo listo.


Creo que si hacemos tal cual hizo el profe hace rato, tenemos que desinstalar el
nodemon y ponerlo como de desarrollo. Arriba, en donde dice start, debe decir
node.

Ahora hay que hacer uninstall del nodemon, desde la terminal.


Ahí se borró el nodemon de las dependencias del package.json

Ahora hay que instalarlo pero con el -D.

Instalamos node_modules. Cómo sería profe en el caso de que ya está instalado y


lo instalamos de nuevo, ¿no pasa nada? No. No habría problema. Algunos quizás
tienen la configuración de que se actualicen, pero en este caso no. ¿Por qué
aparece eso de vulnerabilidades? Porque puede haber alguna librería que esté un
poco deprecada. También salió eso por el tema de cuando salió lo de bitcoin y se
minaba, entonces habían dependencias que lo que te hacían era que te minaban.
Vos las instalabas y te dabas con que te minaban. Entonces en base a eso, fue que
empezaron a agregar el tema de vulnerabilidades.

Miren acá: están haciendo instalaciones de una versión en específico y es como que
está bloqueado y no le da el permiso a que se vayan actualizando cuando nosotros
este ejecutamos la instalación.
Ahora creamos la carpeta middlewares, que no está dentro de src.

Tenemos que tener un archivo que se llama userLogs.txt y otro que se llama
userLogs.js. El userLogs.js va dentro de middlewares.

*********************************************************************

Ahí les pasé por el chat, como info extra, que cuando en el package.json
encuentren el simbolito este, ~, le permite a npm, cuando hacen la instalación,
aceptar parches compatibles.
Si usan la flechita hacia arriba, o el simbolito hacia arriba, permite actualizaciones
compatibles. Y si usan el asterisco permite cualquier versión. Después, más
adelante vamos a ver cómo se instala una determinada versión de algún paquete.
Eso significa que por ejemplo, en debug, que tiene el simbolito ~, significa que si
yo quiero que me acepte cualquier versión, le tengo asterisco en vez del simbolito
~. Pero es complicado, porque puede pasar que en la actualización cambie la
forma en que se usa, y y te termina rompiendo el código, así que hay que tener
cuidado con eso de de dejar todo abierto, que se siga actualizando.

************************************************

El userLogs.txt

Hay que crear una carpeta logs dentro de la carpeta src.

Y dentro de la carpeta logs, creamos un archivo que se llamará userLogs.txt.

Ahora vamos a hacer el middlewares. ¿Qué era un middlewares? Una función que
se ejecuta antes del controlador.

Una opción era hacerla anónima a la función y simplemente hacer module.export =


a esa función anónima; y la otra opción era const el nombre de función y bueno
después hacer el module.export. Pero les recomendaba que lo hagan de la primera
forma, más sencillo. Recuerden que tienen el repositorio también de la comisión,
para repasar. Ya lo subí los cambios. La idea es que entiendan también, que no sea
solamente copiar y pegar, sino que se entiendan los códigos.

¿Qué objetos contenían o teníamos para utilizar en este tipo de funciones con
Express? El request, el response y el next.
¿Y qué va a hacer esto? ¿Qué pedía la consigna?

¿Les parece que primero armen el mensaje? ¿Cómo va a quedar bien? Ha que
agregar el Salto de línea también.

¿Y ahora cómo lo hacemos para escribirlo? Usamos el fs. Podemos requerirlo


entero o con deconstructing. Cómo ustedes prefieran
Empiecen poniendo el nombre y cuando abran el paréntesis visual studio les va a
ayudar en la sintaxis ¿Cómo se llama el método que acaban de importar?
appendFileSync. Cuando abras el paréntesis ya te va a tirar la sugerencia. El
primer argumento es la ruta. Por lo que tenemos que requerir path. También puedes
hacer deconstructing como en la línea de arriba.

Con join,unimos __dirname con la ruta del archivo userLogs.txt, que es el archivo
donde tenemos que escribir: ../logs/userLogs.txt. Y ahora va el segundo
argumento entre los dos paréntesis, que sería el msg. Faltaría el next.

Ya se ha exportado, tiene next para que continúe con la siguiente función de la pila.

Falta requerir userLogs.js en el app.js.


Agregamos app.use(log()) ¿Qué pasa si va con los paréntesis?

Antes que sigamos una consulta: en

¿Por qué no es necesario ponerle la extensión? Porque no es necesario. Porque


estamos trabajando con módulos javascript. Todo lo que sea javascript, lo reconoce.

¿Y ahora cómo hacemos para probar? Hacemos npm run dev.

Creo que está con un error.

¿Cuál es el error? en app.js en la línea 18, los paréntesis en el log. Exactamente,


porque lo que está pasando, es que se está ejecutando no bien se levanta la
aplicación y no cada vez que hacemos un pedido.

A ver qué más. ¿Hay otro error? Ahí tiene otro en la línea 28 de app.js.

No está la ruta, no está configurada la ruta, es tramposo Playground. se llama Main


en este caso.
¿El archivo no es Main nada más? Sí, pero si es que lo vas a usar así con
main.routes, tenes que cambiarlo en app.js, para que coincida Les mencionaba
que estaba bueno dejarlo así, como main.routes, con ese nombre para que se
pueda después distinguir el error cuando se genera uno. Porque van a encontrar
muchos main, y muchos index en node_modules y a veces nos hace confundir
con alguno propio.

¿Cómo se configuraba el routes? En el desafío decía que configuremos las rutas y


todo eso, que queremos un par de get, pero vamos a hacerlo con res.send
solamente que mande mensajito nada más.

Requerimos Express. Requerimos express.Routes y lo guardamos en route.


Definimos la ruta raíz. Como parámetro, le pasamos el controlador.

El controlador no existe. Controlador no hagan. Simplemente hacemos un res.send.


Recuerden que el segundo argumento es una función. Es un callback y dentro iría
la respuesta. Simplemente hacemos un res.send(‘Estás en el Home’), otro
res.send(‘Hola, soy Usuario’), Y así hagamos tres o cuatro para que podamos
tener tres rutas nada más. El res.send lo que te va a hacer es enviarle un mensaje
que diga algo. En este caso, cuando accedamos al Home, ¿Que nos podría
devolver? “Hola, es la raíz”. Y no se olviden del paso más importante para que
podamos utilizar ese router que es exportarlo. Profe, ¿la variable también se puede
Llamar router, como estaba poniendo al principio? Sí, como ustedes quieran.
Generalmente en la documentación lo van a encontrar como router. Pero igual
funciona.

Ahora probamos si funciona el logs.


En la raíz

En usuarios

En productos

Funcionan todos. ¿Y el log está guardando?

Bien. Tenemos listo eso. ¿Qué es eso?


Cuando puse detalle, aparece del proyecto nuestro. Estamos con el tiempo justo.
Nos quedó el segundo desafío, que prácticamente nos pedía que reciba por query si
es que era el nombre de la persona. ¿Recuerdan cómo se manipulaban las queries?
Vamos al navegador y con el signo de pregunta, nombre de la query y el valor con
un igual. Y tenemos más, se concatena con el ampersonal. Por ejemplo, que sea
productos, signo de interrogación y por ejemplo usuario=mac&pass=*****.
Entonces ¿Cómo van a obtener esa query? Del request, van a tener ahí un objeto
que se llama query, y en el query van a encontrar todos los que ustedes creen o
usen, que en este caso uno es usuario y el otro es pass. Con el de usuario ya
cumplen con la ejercitación. No olviden que tiene que ser un middlewares. Así que
ustedes lo van a crear y preguntan si coincide con el nombre x que está con
permiso, lo dejo entrar a la vista, si no, no. Nos va a quedar después implementar
Express-validator.

***************

0:09
en este caso Bueno estamos en una nueva clase que sería la continuación del módulo
número 5 que va a ser de e como
0:16
estamos viendo acá en la pantalla Express validator pero también vamos a hablar de
middlewest que prácticamente
0:22
ya lo veníamos usando utilizando middleware de otras personas en sí o o
0:27
de terceros pero e ya lo implementamos no así que vamos a ver de qué se trata este cómo
se los
0:34
puede utilizar si se los puede utilizar de forma Global en nuestra aplicación o si se lo puede
utilizar en una ruta no
0:40
así que bueno arranquemos Ahí a ver un poquito de eso la música no se escucha no porque
tengo ahí está No no tengo un
0:48
poquito fuerte la música Así que ahí lo bajo y bien justamente los midw van a
0:54
ser como no sé si ustedes llegaron a ver lo que es playground eh middlewares serían lo que
está entre medio de lo que
1:01
va a ser el pedido de la ruta ya sea la petición a no sé home a productos o
1:08
listado de productos lo que sea y la resolución del del controlador no va a ser un paso
intermedio este justamente
1:15
eh agregamos middleware Para ir sacando un poco de lo que son las responsabilidades de
un solo lugar no
1:21
así que vamos a tratar de eh todas las cosas Que tengan un objetivo específico por ejemplo
multer
1:28
que lo usamos para imágenes lo sacamos de la ruta para crearlo o para agregarlo
1:34
a una carpeta que se llamaa midw no bueno La idea es implementar todo Es tipo de servicio
en una carpetita que se
1:41
llama midw bien en este caso Bueno mult solamente lo usamos en las rutas no lo
1:48
usamos de forma global Pero bueno eso es un paréntesis listo bueno acá veamos en sí De
cuáles son los de aplicación dicen
1:55
son Aquellos midw que queremos que se ejecuten siempre que se haga un pedido de
aplicación sin importar a Qué ruta
2:02
esté apuntando el usuario o esté ingresando no bien nos dice que lo implementamos
2:09
justamente usando app.use cuando nosotros usamos el use queremos indicar que vamos a
agregar un middleware o una
2:17
configuración nueva a lo que es nuestro servidor no bien para utilizar este este tipo de
2:23
midw necesitamos funciones que tengan el request el response y luego a algo nuevo
2:30
que es next bien acá Este middleware puede hacer lo que sea no puede ser no
2:36
sé autentificar si es que e el usuario está logueado o si el usuario es
2:41
administrador y demás y si tiene permisos que Eh me deje continuar con
2:47
todo el proceso no de crear un producto o de ver la página en sí del perfil o lo que sea no y
en el caso de que no no no
2:55
eh coincida con lo que nosotros estamos esperando podemos redireccionar a otro lugar o
cortar en sí la ejecución no así
3:01
que están muy buenos estos midw para agregar ahí por ejemplo para validar o para validar
en formularios y demás
3:08
este bien ahí bueno acá Menciona un poco lo que es next como vemos next es un
3:14
callback que se va a encargar de apilar todos los middleware es decir si tenemos 10
middleware se va a ejecutar el
3:20
primero de la de la pila Si nosotros le ponemos un next al final del del código va a pasar al
segundo y así
3:26
sucesivamente no siempre y cuando tenga el next si nosotros no le agregamos el next la
página o el servidor va a quedar
3:33
colgado esperando algo no así que es muy importante agregarle el next a los
3:40
middleware bien y acá tenemos prácticamente algunos middleware que ya utilizamos Cómo
ser el primero que
3:48
configuraba la carpeta donde estaban todos nuestros archivos estáticos que en nuestro
caso están en public y luego
3:55
tenemos otro que sería la configuración de las rutas no no el este enrutador Sería para
4:02
productos pero bueno en este caso no tiene un prefijo como lo usamos nosotros pero bueno
Este es un middleware de ruta
4:09
no as que está bastante Bueno o sea un middleware de aplicación global que está
configurando rutas A eso me
4:16
refiero bien y por acá van a ver un ejemplo de un middleware que se maneja para los
4:23
errores No que ya lo habíamos visto un par de clases anteriores porque nosotros lo
usábamos de una forma diferente no
4:29
bueno esta sería otra forma si es que ingresa un status
4:35
404 va a renderizar la página esa exactamente de 404 Pero
4:41
bueno no quiero hacer foco en eso vamos a lo siguiente midw a nivel de rutas as
4:48
que recuerden globales van en app.js O Nuestro entry Point los de ruta
4:55
van entre medio de lo que sera sería e el pedido
5:03
y ya sea la respuesta o lo que sea que que haga en sí es controlador No pero va
5:09
en el centro bien aora veamos Qué dice al igual que los midw de aplicación los
5:15
de rutas deben recibir tres parámetros el request el response y el next bien en
5:21
muchos casos usaremos estos midw en múltiples rutas Así que es buena idea escribir el
código en un archivo aparte
5:27
Ah para eso ya tenemos nuestra carpetita medware Y requerirlo dónde lo vamos a usar bien
Por ejemplo acá tenemos un una
5:34
función que dice ruta del usuario vamos a verificar si el usuario está logueado cómo
verificaría de la programación de
5:43
javascript para para verificar o para para buscar un condicional en
5:51
Sí si cumple con la condición o no Qué
5:58
opinan cómo manejamos las condiciones nosotros que se ejecute una cosa bien si
6:03
login es verdadero exactamente puede ser puede ser así Si es que bueno el el
6:10
usuario es administrador o si el usuario está logueado si cumple con ese If que me ejecute
alguna acción Ven Bueno Acá
6:18
empieza por el si no está logueado lo enviamos al login nuevamente a la vista y si está
logueado dejamos
6:25
que se siga ejecutando next o que se ejecute next y se sigan ejecutando bueno las demás
cosas no que quizás es
6:33
un un inicio de sesión y bueno y la la vista de de lo que es el su perfil de usuario o el acceso
al
6:42
administrador a lo que sea no bien y acá nos dice Cómo configurarlo supongamos
6:48
que a este midw lo creamos en un archivo aparte luego no olvidemos que para que sea un
módulo necesitamos exportarlo no
6:56
una vez exportado ya lo tenemos listo para para requerirlo miren este hacemos
7:04
un require le indicamos dónde está ese middleware y cada vez que lo necesitamos usar
simplemente lo agregamos ven así
7:11
que antes de que se ejecute Esto va a preguntar si es que el usuario o si el
7:17
user el user es está logueado si el usuario está logueado va a preguntar
7:22
obviamente esto es no es código Pero bueno lo podríamos pasar a código para
7:27
que funcione no Pero bueno se entiende más o menos cómo se lo podría
7:36
implementar nosotros vamos a hacer un ejemplo de justamente de usar un middleware de
ruta pero para Express
7:42
validator y vamos a usar la misma validación para los dos formularios de productos como
para ponerles un ejemplo
7:49
de Por qué nos pide o por nos recomienda que lo hagamos en una carpeta ap parte bien
Entonces hasta acá vamos bien
7:57
no así arranquemos con Express validator que quizás es un poquito más
8:04
e tiene más paso en realidad no es más complicado sino que tiene más paso La idea es que
nos facilite o que nos ayude
8:10
a a hacer una validación correcta No bien justamente Express validator nos
8:18
permite manejar de forma relativamente sencilla todas las validaciones de nuestos
formulario Express validator es
8:24
una librería que se e descarga del not package manag que sería bueno de la
8:30
página no de npm y justamente es una librería de terceros que ya viene e con
8:38
toda la lógica lista para que nosotros la utilicemos para validar formularios para eso sirve
para validar
8:46
formularios así que bueno acá nos indica el paso a paso para hacerlo No
8:52
necesitamos instalar Express validator crear una Ray con la validación de cada
8:59
uno de los inputs de nuestro formulario supongamos que tenemos name price y
9:04
password no sé podemos validar los tres Que bueno que uno sea de tipo numérico
9:10
que el otro sea de tipo alfabético que tenga no sé que no esté vacío que sea un
9:18
email que tenga una contraseña de más de X caracteres se puede hacer lo que
9:25
nosotros queramos no bien así que bueno veamos ese paso a paso npm instal Express
validator
9:33
e esto sería el formulario como Ven Bueno cada formulario tiene un name que
9:39
bueno en este caso el name es name pero después tenemos el otro que es un email y el que
sigue es un password no así que
9:46
cada vez que nosotros queramos validar Algo vamos a usar por ejemplo check o
9:52
Body cualquiera de los dos va a funcionar y dentro del objeto vamos agregando todo lo que
queremos que se
9:57
valide por ejemplo en el campo name quiero que e me valide que no esté vacío si es que
10:04
el usuario Lo envía vacío que me vaya generando un error no que me vaya guardando ese
error para que después lo
10:10
pueda mostrar miren y acá tenemos un listado de todas las cosas que se pueden hacer Igual
Hay muchísimas más No pero
10:17
por ejemplo este tiene que no sea que no esté vacío que la longitud sea entre cco y 10
10:24
caracteres que sea un email y que e
10:30
sea un número entero por ejemplo no tiene mucho sentido Pero bueno no puede ser un
email y un número
10:36
entero por eemplo Pero bueno este y acá en este link van a encontrar muchas más
10:42
validaciones Ven a ver si si se llega a ver si es buano por ahí si es que es un
10:47
bulano eh si es una fecha eh qué más si es de hexadecimal un
10:57
Stream con hexadecimal no sé van a encontrar un montón si es
11:06
numérico no sé Hay un montón si les interesa ahí lo tienen el
11:12
link como para ir investigando un poco más de eso pero creo que acabo de cerrar la
11:18
diapositiva Así que vamos a abrir de nuevo y vamos a donde quedamos Bueno ya una vez
cuando
11:25
nosotros tenemos todo definido de lo que queremos prácticamente ya podemos
11:33
ir justamente exportando esto Ven Bueno algo así quedaría supongamos que tenemos
11:38
name email y password ahí le hago un poquito de zoom que por ejemplo el name
11:45
o el input que se llama name no puede estar vacío y si está vacío que me
11:51
genere este mensaje debes completar el nombre luego agrega algo que se llama punto que
no sé si lo mencioné en algún
11:57
momento Bale no lo mencioné no pero prácticamente Bale lo que va a
12:04
hacer es cortar más adelante está profe Acá está claro ya estaba mezclando todo
12:09
pero bueno acá como ven dice que el método Bale lo que va a hacer es cortar
12:14
la validación aquí es decir no continúa validando el resto de Campos que se viene más abajo
sino que te genera el
12:22
primer error y te dice Bueno corregime esto y después sigo validando los demás está bueno
cuando son no sé una
12:28
lista de vamos que tienen 20 Campos ir cortando
12:33
uno por uno para que bueno se vaya haciendo e de forma ordenada
12:39
no pero bueno este qué más les iba a mencionar el Wi message que cada vez que
12:45
no coincida con algún o que en realidad no cumpla con alguna de estas cosas que
12:50
me genere el mensaje Por ejemplo not empty el mensaje que va a mandar es
12:56
debes completar el nombre después si se genera algo con el error que sea menor a cinco
caracteres
13:04
el nombre debe tener al menos cinco caracteres ven Está bueno porque vamos generando
nombres a medida que
13:10
e que vamos vamos haciendo una determinada un determinado error no esto
13:16
sirve un montón para para que sea más descriptivo el tema del error para el
13:22
usuario bien bueno y acá dice en algunos casos vamos a querer cortar la validación ya que
por ejemplo un campo
13:28
está vacío no tiene sentido verificar si el email es válido bien profe una pregunta el mail sí
corta solamente eh
13:36
Para todos los chequeos del en este caso el email exactamente y Pero puede
13:41
proseguir con los otros Por ejemplo si el campo password Okay exactamente por ejemplo
acá lo tiene en que se fije que
13:49
no esté vacío y lo corta ahí si es que bueno viene vacío directamente te manda este mensaje
y deja de validar lo demás
13:55
porque puede ser que tenga mucha validación este y en caso de que cumpla y ya no esté
vacío va a pasar recién al
14:03
siguiente y ahí se va a fijar si cumple con el requisito de que sea un email no aunque tenga el
formato de un
14:09
email bien nosotros una vez que ya tenemos armado todo lo que es el array
14:14
con todas las validaciones en este caso Bueno lo guardamos en una constante o no la
guardamos como nosotros queramos pero
14:21
lo exportamos para que se convierte en un módulo No porque nosotros vamos a usarlo
justamente en un middleware y
14:27
después vamos a exportar esa validación bien cuando ya tengamos listo lo que es el el el
array con todas las
14:34
validaciones lo Podemos agregar como midw ahí justamente de e de ruta no así
14:41
que agregamos ahí todas las validaciones es decir cuando el usuario haga clic en
14:47
el botón enviar o crear producto o lo que sea o en este caso el registro
14:53
cuando él del click en el botón registrarse va a pasar primero por Esta
15:00
validación bien si es que hay errores lo que va a pasar es que todos esos errores
15:06
se van a ir guardando en un objeto y bueno justamente Bueno después va a pasar por acá y
acá es donde podemos
15:13
atrapar los errores y manipularlos no que bueno justo esa diapositiva me falta pero eh ahora
mismo la comparto la tengo
15:21
por acá para descargar Pero bueno hasta acá ya estamos no tres pasos tenemos vamos
viendo tres de eh cinco creo que
15:28
son de de de Express validator esto estos controles solamente se hace cuando
15:34
se va a guardar datos profe exactamente esto sería cuando eh necesitamos por
15:39
ejemplo crear un producto actualizar un producto o loguear noos o lo que sea todo lo que
sea con manipulación de
15:45
formularios bien se entiend porque en este caso como ven acá estamos usándolo en un
post puede ser en un put también
15:53
tranquilamente pero bueno vamos a la otra ppt que decía eh Express validator
16:00
avanzado as que ya estamos en el paso número cu ya instalamos Express
16:06
validator ya creamos una array con todas las cosas que queríamos validar
16:11
justamente agre ya lo agregamos ahí a la ruta como middleware es decir entre lo
16:17
que es el la ruta en sí y el controlador no luego verificamos
16:24
si es que hay errores en la validación del controlador nos falta eso y luego enviarlos a la
vista porque todavía no
16:31
estamos haciendo eso acá hasta acá solamente se está guardando en un errors
16:36
por ahí en un resultado en Sí pero no lo estamos usando de ninguna forma Así que vamos a
usar otro objeto en sí de o otro
16:46
Método en s de exess validator que se llama validation res result en este caso Bueno ya
mentalmente
16:54
nos vamos a user controllers al controlador en sí
16:59
requerimos esto no requerimos esto y luego en el controlador donde queremos
17:05
utilizarlo o en el método vamos a eh guardar este resultado el result
17:12
validation de lo que viene del request lo vamos a guardar en una variable que le podemos
llamar errors errores como
17:17
nosotros queramos No pero va a ser el que va a guardar todo el listado de errores de cada
campo la los errores que
17:23
contiene no hasta acá estamos H no no
17:28
bueno no no eh desde dónde lo invocamos esto O sea nosotros Nosotros el último
17:36
paso que hicimos fue meterlo en el como middleware en la ruta ahora Este paso va a ser
utilizar
17:43
toda esa información que se va guardando no así que nos vamos al user controller por
ejemplo requerimos esto que nos
17:51
indica acá la la documentación y luego en el post de register o como como se
17:58
llame el método o procer register como le queramos llamar en ese método vamos a
18:04
guardar una variable el resultado de de esto el validation result y esto nos va
18:11
a traer un listado una rayon en realidad nos va a traer un Eh sí una Ray con los
18:17
resultados con todos los errores si es que bueno si es que los hay no ya lo vamos a ir viendo
esto con un ejemplo
18:22
con conso log y demás Así que bueno acá eh Como ven
18:27
tienen un ejemplo miren Uy este en este caso Este es un el método register no lo
18:36
primero que hace es guardarlo en una variable como Ven a ese resultado y luego pregunta si
es que errores está
18:43
vacío que esto es otro eh método de validación No que ya está dentro de de
18:49
Express validator bueno pregunta si es que está vacío es decir si no hay errores que Eh
bueno en este caso eh Me
18:58
agregue el objeto nuevo con el con el usuario que escriba el Jason y
19:04
que me redireccione no sé a la vista del del perfil del usuario por
19:09
ejemplo esto es si no hay errores pero si es que hay errores vamos a volver al
19:15
formulario y decirle Che para las credenciales no están bien o la contraseña está mal o el
bueno no se
19:22
recomienda eso en realidad Porque bueno eso puede ser que eh sea alguien malicioso que
intente eh Ingresar a tu
19:29
perfil y si nosotros le decimos el usuario está mal Bueno va a probar con otro usuario hasta
que le pegue a uno no
19:36
pero si nosotros le decimos el password está mal va a empezar a probar con todas las
combinaciones posibles hasta que lo
19:42
pueda romper en Sí al al encriptación del código no de la contraseña Así que hay que tener
ojo ahí en este caso en
19:49
específico de registro de logueo con el tema de cómo mostramos lo lo que está
19:55
bien o mal pero bueno ahí podemos ir mostrando de forma descriptiva Cuáles son los
errores No bien y luego encontramos un
20:03
método que está bueno dependiendo cómo queramos manipular lo que son los errores Qué
sería
20:09
mapet como ven dice mapet nos permite enviar los errores a la vista como un objeto porque
yo les mencionaba que era
20:15
un array Es decir para que nosotros podamos manipularlo íbamos a tener que hacer un for
each por ejemplo y y luego
20:21
íbamos a poder ir imprimiendo esos errores prácticamente Pero con esto con el con
20:29
el maped lo que podemos hacer es ya acceder a los errores de a ver los
20:35
errores de email y al mensaje a los errores de password y al mensaje Ven y
20:41
acá es más acá se ve el value que puso y demás Pero bueno eso hay que tener ojo también
ojo también con esa cosa pero
20:48
pero bueno la ventaja de eso es que podemos manipular lo que era el
20:53
valor anterior que puso la información anterior y demás
20:58
bueno y el último paso porque acá ya prácticamente lo tenemos lo enviamos ahí mapeado
no al error y acá mandamos algo
21:05
que dice qué sería ese hablando Siempre de El caso en que
21:13
el el usuario se quiera registrar y bueno tenga algún error el formulario no le devuelve los
datos Supongo para
21:20
que los ingresas bien exactamente le devuelve los datos justamente porque puede haber
datos que si estaban bien y
21:28
esos esos datos necesitamos que sigan estando porque si no se vuelve tedioso no sé si les
pasó a ustedes que
21:33
intentaron registrarse en alguna página o ingresar alguna página y si se
21:38
equivocaban le dejaba todo el campo todos los campos del formulario en blanco y les
tocaba de nuevo hacerlo a
21:43
mano cargar todo y es super tedioso bueno La idea es que nosotros ya les
21:49
dejemos precargado todo lo que está bien y solamente eh cambiemos los valores de lo que
está mal
21:55
no se entiende para qué sería el o le podemos llamar all Data como queramos pero es la
información que venía antes
22:01
en el formulario bien y simplemente para mostrar los errores vamos a agregar un
22:08
condicional ahí preguntando si es que existen errores y si hay algún error con
22:14
e el nombre name este y justamente bueno de esa forma
22:21
vamos a acceder va perdón si es que coinciden o si es TR las dos cosas vamos
22:26
a eh crear una p que nos muestre el nombre del error ven en este caso puede ser no
22:35
sé que en este caso creo que debería ser errors
22:42
punto message o mensaje dig msg para que nos salga debes completar un email
22:48
válido Ya lo vamos a probar Pero bueno Me parece que eso Habría que ver bien Ah y acá
recuerden también que debemos
22:56
agregar los datos anteriores si es que venían datos correctos acá le
23:04
damos locals o si es que venía old Y si venía la propiedad de email lo agregamos
23:10
nuevamente no para que no molestemos en al usuario así que bueno les parece que lo
implementos en el proyecto ese donde
23:17
estábamos trabajando la la clase pasada todo esto todo esto que has visto
23:24
la segunda parte avanzado todo esto es dentro de controlador todo e Sí desde el
23:30
controlador hasta el paso donde lo enviamos a ljs que está acá ven que este es el
23:36
Label y el input de de cada uno de los de de los de los campos no que queremos
23:43
agregar el mensaje la ventaja de hacerlo con el maped justamente es que Podemos
23:48
agregar mensajes personalizados acá no en cada uno de los espacio donde queremos
Porque si nosotros usamos el
23:54
sin el sin mapear nos va a llegar una Ray y ese tendríamos que hacer un forage en alguna
cajita de alguna parte de la
24:01
pantalla no esta parte sería entonces en la vista exactamente esto ya sería en la
24:06
vista Ah okay Y otra preguntita profe porque he visto en el material como como
24:14
dividida las opiniones o o parece por lo menos algunos Usan el check y otros el
24:20
body sí no estoy muy segura de entender la diferencia funciona funciona
24:26
Exactamente igual debe tener alguna condición ahí yo estaba investigando y y
Aparentemente el check se usa más cuando
24:33
cuando usamos queries pero este yo lo probé con el por lo menos para los post
24:39
los probé con con Body y con check y funcionaban igual así que no habría problema con
24:48
eso bien empecemos entonces con eh implementar todo lo que veníamos o
24:55
continuar con el proyecto y le agregamos validaciones a los formularios así que bueno me
voy a la carpetita de la comi vamos a buscar nuestra comisión
25:02
por acá que en este caso la última que usamos fue clase 30
25:09
crud up pero no vamos a hacer en la 29 que estaba el CR
25:15
2 voy a crear una carpeta nueva que se llame clase 31 sería la de hoy no
25:23
middle y vamos a copiar lo que tenía la 29
25:29
vamos a sacar estos no modul que me están ocupando espacio Ahí Ah ya acabo de hacer
creo que ya
25:38
hice creo que me va a dar error cuando pegue Ah Sí ahí está bien Ahora acabo de
25:44
eliminar que tenía copiado para pegarlo en otro lado pero bueno no importa listo
25:49
arranquemos con esto tenemos el proyecto prácticamente
25:55
continuado de lo que era el crud no Qué opinan Si e empezamos ahí se
26:04
acuerdan toda la estructura de este como era teníamos ya configurado nuestro package
json voy a cerrar un poquito las
26:10
ventanas Ahí está teníamos configurado nuestro package json justamente con
26:16
todas las cosas que venían en nodemon no en Express validator que había cosas que ni la ni
sabíamos para qué servían Pero
26:22
bueno están ahí bien Vamos a instalar justamente
26:28
o empecemos agregando un middleware de un middleware de e de forma global no que nos
vaya
26:34
haciendo un loog que nos vaya diciendo bueno tal usuario entró en tal lugar a
26:40
tal hora les parece como para tener algo algo extra nosotros ya teníamos el midw
26:45
de multer que prácticamente lo que hacía es configurar dónde Cómo o sea dónde se
26:50
guardaba cómo se iba a llamar y qué archivos recibía en este caso recibía solamente eh
imágenes no el tipo imagen
27:00
y lo exportamos para poder utilizarlo obviamente porque es un midw lo exportamos bien
Vamos a crear otro mw
27:07
que para seguir con lo que es el ejemplo que estaba en la grabación la pudieron ver la
27:15
grabación yo no bueno tampoco Bueno prof a lo de la clase a la de hoy por ejemplo
27:23
ahora vamos a hacer una un midw de forma global que este va a tener como objetivo
27:29
cada vez que un usuario entre a nuestra aplicación o a nuestra página vaya
27:34
guardando por dónde va esto a veces está bueno para ir haciendo un análisis de Mercado y
decir Bueno
27:40
a al no sé a x cantidad de personas le interesa más entrar por el lado de donde
27:46
son las vistas de las zapatillas de tal categoría por ejemplo no bueno algo así
27:51
se usa el algo así sería la lógica no Pero bueno vamos a empezar en este caso
27:58
yo como les mencionaba quiero ir guardando eso vamos a crear una
28:03
función que en este caso va a tener el Rec el res y el next
28:12
bien como yo esto voy a exportarlo simplemente voy a hacer una una una
28:19
función anónima ven esa sería una opción o si no
28:24
la otra opción sería como lo veníamos haciendo a ver comento un poquito
28:31
eh function Y le podemos llamar logs va a ser Eh Esto
28:38
reges next tuki Ven y después teníamos que hacer
28:44
module punto export de logs bien yo para
28:50
no estar haciendo eso abajo directamente le exporto la función es exactamente lo
28:55
mismo se entiende o quieren que volvamos a como está así
29:00
no está bien entiende profe es para mencionar o sea es para mostrarle que se puede hacer
de esta forma también sin
29:07
necesidad de ponerle un nombre no porque después nosotros esto lo importamos y lo
vamos a importar con con ese nombre o
29:12
con el que queramos milanesa lo que lo que sea así que
29:18
bueno Recién veo el chat que decía los restal y Sí Prácticamente están Todo el
29:24
tiempo escuchándonos no no sé si Bueno a ustedes les pasa yo ahora estaba viendo una
una mochila para la Notebook
29:32
y me sale en todos los lugares donde entro me salen mochilas bolso cartera ya
29:39
es super tedioso el el tema pero bueno
29:44
empecemos con esto nosotros e vamos a generar un mensaje le podemos
29:49
llamar mensaje o message no sé algo así y ese mensaje va a ser una concatenación
29:56
de el usuario ingresó ingresó en la
30:04
URL dos puntos y acá vamos a agregar o vamos a utilizar lo que venga del request URL que
no me acuerdo si era con
30:12
mayúscula o minúscula Pero bueno vamos a generar un mensajito que diga así y le
30:17
vamos a poner que a las x x horas porque todavía no sé
30:25
cómo usarlo est bien qué más necesitamos necesitamos obviamente un
30:32
lugar donde guardar este mensaje así que vamos a crear acá un archivo en Data
30:38
que le podemos poner blogs txt va a ser de texto así que
30:46
bueno ya tengo el archivo creado lo vamos a dejar por acá a ver Hagamos una ventanita
compartida tuki
30:53
bueno acá tenemos un L para ver si es que pasa algo cuando se ejecuta en este mw Y qué
más necesitamos usar un módulo
31:02
obviamente para escribir ese ese logs.txt qué me recomiendan
31:08
usar para escribir un archivo o para manipular un archivo
31:15
fs exactamente
31:20
con fs y vamos a usar el F
31:25
pero como simplemente voy a usar el gr F sync no me quiero traer
31:34
todo el fs Así que vamos a hacer eso cómo se llamaba esto que hacíamos
31:42
acá estructur d estructuración exactamente estamos d
31:47
estructurando o obteniendo solamente el método Great filec de todo lo que es el
31:53
este objeto con distintos métodos que es fs así Así que simplemente vamos a
31:59
traernos gr Fil sync la idea de eso es para que no esté haciendo fsg Fil sync a
32:04
cada a cada rato simplemente y también para no traerme todo no porque ahora
32:09
Simplemente estoy leyendo eh gr file sync de todo de lo que es el objeto así que bueno gr file
sync necesitaba dos
32:17
parámetros el primer parámetro como nos indica ahí en en selecte azul es el la
32:23
ruta no así que vamos a usar pad que a ver si me da la opción de
32:29
requerirlo No no me da a veces te da la opción creo que ahí está miren cuando le
32:37
salga ese simbolito de acá así y presionamos Tab podemos requerirlo
32:43
ven ahí se hizo el require de forma automática bien y de p vamos a usar join
32:50
Así que podemos hacer también ya que estamos simplemente vamos a usar join de
32:56
pat Ahí está bien y pad para qué nos servía
33:03
como dice acá une todos los argumentos y demás y los normaliza en si así que
33:10
bueno vamos a unir deame con en este caso dónde estamos parados en logs Me
33:16
parece que tenemos que volver una para atrás entramos
33:21
a Data o Data y luego a logt
33:28
bien funciona esto no funciona estamos bien Con la ruta o no vamos a probar podríamos
hacer un el uso también de
33:36
otro método que se llamaba exist sync que preguntaba si es que
33:42
existe pero no vamos a dejarlo Ahí vamos a jugar a la suerte de que ya teníamos un l. XT Y
en este caso vamos a usar
33:49
appen file appen filec que lo tengo que
33:55
traer file Ahí está bueno entonces vamos a
34:01
usar solamente appen file porque nosotros queremos que a medida que vayan ingresando a
todas las páginas se vaya
34:07
agregando el contenido y no que se vaya eliminando no así que bueno acá hay algo más que
me
34:13
gustaría hacer y es un salto de línea no me acuerdo cómo era el símbolo Así que
simplemente lo voy a hacer con la con
34:20
con este tipo de concatenación que me gusta usar a mí creo que era barra n profe creo que
sí pero no me acuerdo si
34:26
era invertida la bar creo quea bar invertida por eso no invertida este así que bueno ya
exportamos esto ya lo
34:35
tenemos exportado Así que tranquilamente lo podemos importar como va a ser un
middleware de forma global quiero que se
34:44
vaya ejecutando en todas las rutas lo vamos a meter acá Así que arranquemos con el
34:50
require llamamos l Creo va a ser require le indicamos la ruta donde está
34:58
tenemos que Ingresar a Data Simplemente porque nuestro a. js está a la misma
35:04
altura de lo que es la carpeta Data no así que decimos que lo que queremos
35:09
obtener es logs y luego lo tenemos que utilizar que en este caso lo vamos a meter acá otro
midw que se llama en este
35:18
caso logs bien Y ahora cómo lo probamos a
35:25
esto o esto qu pas Qué pasa acá no no se reconoce como Comando interno o externo
35:33
Qué pasa aquí Me está faltando algo a ver si funciona npm Start algo Me está
35:39
faltando que piensan que está pasando acá nos dice no está instalada
35:47
no pero acá me tiró otro error creo que me faltó algo cuando
35:53
copie el proyecto el mod de Express tien que instalar tod la librería no exact falta
36:01
falta Todo aparte de falta todo no tenemos nada nada de no modules y bueno
36:07
justamente en el package json ya tenemos tod lo que hace falta todas las dependencias
Pero bueno falta instalar
36:12
así que np me instal esperos que instale todo todo todo me dice que es la última librería
36:21
que tiene Ah esa uid Esa era la que habíamos usado para generar el ID único
36:28
para cada producto se acuerdan que estaba por a ver dónde está creo que estaba en este
36:34
método y cada vez que ejecutaba ese u ID
36:39
b4 que s yo lo que hacía era generarte
36:45
una serie de caracteres y demás que eran únicos No para identificar para que no
36:50
se nunca coincida uno con el otro de los productos que vamos creando se
36:55
acuerdan Sí sí bien bien buenísimo así que bueno ahí tenemos instalado todo Me
37:01
parece que ya debería funcionar Así que le damos a npm rander y me dice que no me
37:09
encuentra el módulo puse mal la ruta puede ser a ver dónde está el error ahora ustedes me
van a empezar a ayudar
37:15
con los errores porque estoy cansado Ah somos
37:21
dos somos tres miren en los lugares donde lo está requiriendo Aparentemente
37:26
acá pero dónde lo estamos usando en App en App línea 8
37:35
dice veamos el app línea 8o y veamos si coincide con lo
37:41
nuestro bien está bien
37:50
Esto se llama alx Ah bien qué estoy
37:55
intentando requerir yo está buscando un js tiene otro formato el
38:00
archivo carpeta est intentando
38:09
accer buen apur así que
38:17
bueno y veamos pasa
38:24
bien quear
38:29
listo Bueno ahí ya va cambiando un poco el error no pero acá me dice que a
38:35
ver dice por acá a ver si encontramos algo
38:40
familiar. js línea 20 lo parece que está bien Me faltó algo
38:50
me faltó algo
38:55
falta e puede ser pero no me parece que no igual ahí eso me estaba faltando que
39:01
es el next para que continúe después que pase de esto nos falta la s en el export
39:07
o no ahí está exactamente y acá también tenemos un error miren nosotros estamos
39:15
en el app file sync Recuerden que el primer parámetro es la ruta no y el
39:20
segundo parámetro es la información que queremos que se agregue en este caso no
39:26
tiene nada como para que se agregue Así que nos falta el segundo parámetro que es el
mensaje ese que creamos
39:31
arriba hasta acá estamos y ahí Bueno ahí me sale que el puerto está en uso y
39:37
demás Ah bueno Y acá tenemos un error de Puerto en realidad Porque creo que yo
39:43
tengo levantado otro servidor con el mismo Puerto vamos a hacer un RS para ver si ahí está
ahora sí okay estamos en
39:51
el local 3000 Recuerden que cada vez que yo hago un ped
39:56
a cualquier ruta se me debería ir escribiendo en el ahí se ve a ver se
40:02
debería ir escribiendo en nuestro logs Bueno ingresemos a esta ingresemos
40:08
a productos create ingresemos a listado de productos y volvamos a ver qué
40:17
pasó miren funciona funciona funciona Elmo ahí así que prácticamente estamos
40:24
no pero nos falta lo nuevo lo que yo les comentaba que íbamos a agregar algo extra y va a
ser en si manipular lo que
40:32
es la hora y los minutos en s en lo que se está ejecutando así que bueno vamos a
40:37
crear una constante que le podemos llamar Time o no s el tiempo en este
40:43
momento Y eso se genera con New date New date esto es javascript no no es nada
40:51
instalado Nada que es y esto nos va traer muchísimas cosas
40:56
no va a ser un un objeto con muchos métodos dentro de los cuales van a tener
41:02
por ejemplo get Gear get hours no se pueden traer minutos segundo
41:08
lo que ustedes quiera pero bueno en este caso a mí me interesa la hora y acá los
41:14
minutos Así que vamos a usar acá tuki símbolo peso para peso llave
41:21
para agregar una variable nueva le vamos a llamar Time get
41:27
obtener horas y el siguiente va a ser
41:34
Time punto get minutos obtener minutos y me falta
41:41
ejecutar la función para que me devuelva los minutos efectivamente
0:01
y vamos nuevamente a probar la página así que bueno vamos ahora a milanesa milanesa
detail bu ahí me
0:09
dice que no no existe obviamente y como ven el usuario ingresó
0:14
o intentó ingresar en la URL milanesa detail a las 15 29 horas se entiende
0:21
esto se entendió yo entendiendo para o sea como
0:28
en AC esto con los del middleware esta partecita Este es el
0:35
middleware que creamos el objetivo de este medware es cada vez que un usuario
0:41
ingrese a una página me vaya guardando en algún archivo de texto a dónde fue
0:47
que ingresó ven Ah Per estás haciéndolo primero y probando la función y después lo vas a
poner en la y después lo vas a
0:55
poner en el controlador o no No en este caso es Global en este caso al ser
1:00
global claro al ser global ya no hace falta que lo metamos en cada ruta esto
1:06
ya funciona en todas partes perfecto hice el require acá claro hice solamente el require acá
1:14
y acá lo lo metí al logs es decir bueno cada vez que el usuario ingrese que vaya
1:19
creando así uno podríamos hacerlo más complejo y bueno obtener el nombre del usuario y
bueno que el usuario es tal
1:26
ingresó a tal página a tal hora ir guardando un logs por usuario o ir
1:31
haciendo No sé lo que lo que se imaginen se puede hacer pero está bastante bueno Esto de
hacer un seguimiento
1:39
bien Creo que y bueno justamente es el dat er de esa forma No podemos guardarlo
1:45
también en
1:51
con minutos va a ser igual a Time
1:57
get minutos y acá directamente ya le decimos que vamos a usar minutos
2:03
No pero bueno es lo mismo era para
2:08
no y acá sería lo mismo con
2:14
horas ser igual a get
2:20
hours Ahí está ven ahí queda un poquito mejor el mensaje pero arriba estamos
2:26
haciendo todo la el guardado en sí de cada uno de los valores
2:32
bien Esto es prácticamente lo mismo que estaba en playground así que bueno nada
2:38
más que le agregue un poquito más de de estilo pero es prácticamente lo mismo no
2:44
así que bueno vamos ahora lo más interesante en sí de la clase o lo más importante de la
clase de hoy que
2:50
eh sería justamente agregar Express validator y después bueno obviamente van a tener que
hacer la ejercitación hoy no
2:56
no se salvan de eso así que efectivamente para que funcione esto voy
3:02
a dejar levantado no más para que sigamos con esto levantado abro otra terminal y vamos a
instalar Express
3:07
validator primer paso espr
3:15
validator algo que vi también ahí que no me gustó que ya viene preconfigurado en
3:21
eness generator es que no Demon viene instalado como
3:27
dependencia global o de producción yo les mencionaba que esa es una
3:33
dependencia de desarrollo Así que lo vamos a desinstalar npm uninstal
3:38
noon también como para que vean que se puede eliminar librería si nos equivocamos
podemos desinstalar de esa
3:45
forma y luego le instalamos de nuevo npm instal nodemon gu d info extra como para
3:54
que para que puedan ver que se puede instalar cosas desinstalar cosas
4:01
instalar eh Como de dependencia O desarrollo como ustedes quiera profe sí
4:07
no escuché en este caso por qué convenía desinstalarlo porque nosotros cuando
4:14
cuando lo usamos o sea cuando nosotros el proyecto esté listo listo listo para producción
vamos a usar este Comando
4:21
node claroo es es este no y este solamente lo usamos cuando estamos de
4:27
forma local en desarrollo exactamente Ajá así que eso Debería ser una dependencia de
forma
4:33
eh de desarrollo no pero se lo desinstala o se lo deja de usar no más
4:38
cuando directamente se lo desinstala no no habría problema ahí como estás Ya no habría
drama porque para que funcionen
4:45
el proyecto va a instalar todo esto cuando ya nos vamos a producción no y a
4:50
esto lo deja como de lado Ajá bien
4:56
e ceremos todo ceremos todo y arranquemos ya acabamos de instalar eh
5:02
Express así que bueno arranquemos con eso arranquemos con eso necesitamos un archivo
midw nuevo que justamente vamos
5:10
necesitamos nosotros ya tenemos el formulario que estaba por acá a ver dónde está
nuestro formulario tenemos el
5:18
formulario de creación de productos y el de edición de productos prácticamente
5:23
tienen lo mismo así que nos puede servir por los dos vamos a crear un mid alg nuevo que se
llame eh
5:34
validate products pun js porque justamente nos va
5:40
a servir para hacer la validación no y vamos a empezar a traernos todo lo que
5:46
necesitamos validar voy a traerme Body justamente de
5:52
Express validator require Express validator y ahí vamos a
5:58
empezar a armar este de objeti que vamos a hacer lo mismo de hace rato module punto
export igual a un una Ray
6:09
perdón no era un objeto y acá va a tener lo que sea del campo nombre lo que sea
6:14
del campo precio y demás Así que como no me acuerdo el nombre de cada cosa voy a
6:20
abrir una nueva ventanita acá con el formulario para que vaya bien
6:25
y ya que estamos con visual Studio vamos a usar la lup para que me ayude a buscar las
cosas vamos a poner
6:33
que todos los name me los me los deje como sombreados ahí como que me vaya
6:38
ayudando ahí a identificar así que bueno el primero es name Qué vamos a
6:43
hacer con el método Body vamos a validar lo que contenga name qué podemos validar
6:51
de El del del nombre del producto que no
6:56
sea vacío bien es era con not empty bien
7:03
y le podemos hacer un mensaje ya que estamos with message message
7:09
el nombre del producto o debes ingresar un
7:14
nombre un nombre para que seamos más eh Y ahí podemos hacer un bail también como
7:19
para que diga Bueno si hay error Quédate ahí después qué más puede ser
7:26
de de en el caso de El input de tipo name es un texto Así
7:33
que podríamos decir que sea alfanumérico miren que acá tienen un montón de
7:40
validaciones date decimal cas y demás Pero ya lo perdí al Alfa numérica Ahí
7:51
está y creamos un mensaje nuevo que tenga no
7:56
s ser un un texto no sé algo así listo eso
8:02
nada más para que no perdamos tiempo con listo Después qué más tenemos Ya hicimos
name qué más me
8:09
falta tanto voy escribiendo la estructura qué otro campo del precio
8:17
bueno price que esté vacío y que tenga el
8:23
mensaje with message ingresa un precio
8:30
qué más tenemos otro campo más Body a ver qué más tenemos por
8:36
acá tenemos Discount como ven acá tenemos category tenemos description así que
8:45
bueno voy a copiarme este profe el del precio por ejemplo le debería poner que
8:51
solamente sea numérico O sí estaría bueno Estaría bueno que sea numérico también o sea
digamos usted desde el
9:01
html el html pede digamos bloquear eso pero si uno lo cambia igual ingresaría
9:07
Digamos como como por ejemplo si lo cambiamos a texto editándolo igual ingresaría Claro
ese es el problema de
9:14
usar formulario o se usar una validación en el formulario en el html en realidad
9:20
Porque a ver produ barate por ejemplo si nosotros acá
9:26
tenemos un descuento en este caso cre que descuento es numérico y deber ser Perdón este
texto esto Debería ser un
9:34
número y este también Debería ser un número pero está con un input de tipo texto eso está
mal pero bueno supongamos
9:42
que nosotros lo tenemos como número Este tranquilamente el usuario
9:47
puede decir no Bueno yo quiero romper esto y y a este input en vez de que sea
9:53
de texto quiero que sea number y ahí Cuando intento poner una
9:59
letra no me deja no así que solamente son números este y si le da enviar nos va a enviar
10:05
esta información así de esta forma no es más e algo que no les había mostrado en esta
10:11
Comic todavía era de que hay que tener ojo con dejar el spread operator en la creación de
productos porque a ver en
10:19
este caso Este input es de nombre price no Pero podemos hacer uno que se llame
10:24
eh Access o algo así que tenga algo alguna cosa encriptada o algo y puede
10:31
llegar a a mandar información en el body que que nos Abre alguna puerta ahí posible
10:37
e un posible problema no que nos robe información o que no nos genere algún problema
con la
10:44
aplicación Así que hay que tener ojo ahí con esas cosas ya lo vamos a corregir a
10:49
eso bien eh teníamos precio qué más teníamos
10:58
descripción y vamos decimal profe también puede ser si es que lo tenemos
11:04
configurado así puede ser Per bueno
11:09
agreg number numic que sea
11:16
numérico y nada más bueno agamos mensaje message el precio debe ser un número que
11:26
creo que esto va generar un error en base emos porque estamos recibiendo un texto y acá
podemos hacer un punto como
11:33
para decir que se corte Si es que llegó el primer error y bueno si no que sig listo y description
le pongamos debes
11:39
ingresar una descripción profe hay que cambiar el formulario
11:45
Entonces el tipo de dato habría que cambiarlo lo cambiamos ya que estamos lo
11:51
tenemos por acá Dónde está el de precio price
11:57
tipo number Ahí está veamos que haya quedado
12:04
bien Ahí está bueno Ahí sí quedó bien porque ya no me deja escribir y bueno y ahí nos dice
number así que bueno
12:11
prácticamente lo tenemos listo se pueden a seguir haciendo todas las que nosotros
queramos pero para no perder tiempo con
12:19
esto lo dejo hasta acá validaciones quedan hasta aquí Recuerden que bueno
12:24
tienen un montón para para ver para agregar cuantas más agreguen mejor para bueno para
evitar esos
12:31
posibles e esas posibles brechas de bueno de de
12:37
rotura de nuestra aplicación no así que bueno paso dos Listo ya
12:46
tenemos lo que queremos validar paso tres nos vamos a nuestra ruta donde lo
12:53
vamos a usar que en nuestro caso Uy en nuestro caso sería en
13:02
products requerimos justamente este midw que le vamos a llamar
13:07
e validations
13:15
middleware y acá vamos a hacer el require Pero bueno ahí iría el require
13:20
Ya lo vamos a acomodar como no tengo ganas de escribirlo directamente lo meto acá y uso
visual Studio se llamaba el
13:28
archivo validate products
13:33
validate products y no lo reconoce Así que lo voy a tener que hacer a mano
13:39
validate Pro ducts Ahí está y vamos a requerirlo con validate
13:47
product igual a require le indicamos la ruta que en este caso tenemos que volver
13:53
uno hacia atrás Ingresar a middlewest y efectivamente agregar o Ingresar a
13:58
validate products algo ahí para hacer un paréntesis Es que la ruta va de esta forma primero
va
14:07
esto que es multer luego va la validación miren y
14:13
acá lo hice mal no porque esto lo vamos a probar primero en el formulario de eh creación de
productos y no de edición
14:23
Uy a ver qué dice corto pego y como ven cuatro parámetros
14:32
exactamente en este caso tenemos cuatro argumentos el primero va a ser la ruta y los
segundo van a
14:38
ser justamente middlewares el segundo middleware el tercero un middleware más
14:45
Este es de procesamiento de la imagen este es de
14:50
validación de productos y bueno y este ya es el controlador que nos hace lo que
14:55
es el guardado del producto y demás que eso lo hicimos la clase hace dos clases
15:01
en realidad que lo que hace es generar un ID único se fija si la imagen existe
15:06
o si viene una imagen y si no le pone por default agrega lo que viene en el body que ahí está
lo que yo les decía
15:11
que es peligroso porque acá estoy dejando oportunidad que la gente inyecte
15:18
más información no puede inyectar cuas cosas quiera ahí en el body profe hasta Cuántos m
se puede
15:25
agregar Lo que ustedes quieran ah no hay problema con eso siempre y cuando no se olviden
de agregar el next para que
15:33
justamente pueda continuar con la ejecución no con la pila de ejecución no pero me refiero
ahí en las red en las
15:39
rutas Perdón ahí que usted puso Sí sí como puede ser 3 c ahí puede
15:46
ser lo que quieran Ah este siempre y cuando tenga el next como les mencionaba y y la
ventaja es que no tenemos todo lo
15:52
que es la lógica acá dentro de esto no porque si no tendríamos que hacer acá el
15:59
el callback con el con todo lo que es el Rec el res y el next acá otro callback
16:06
más acá otra función y se iba a ser gigante el código no y ya se I a volver
16:12
claro por eso ya directamente cada uno tiene su responsabilidad el midle World validate
product valida los campos del
16:19
formulario el middle World multer valida que o me crea un destino de o me crea la
16:26
imagen con un nombre en específico y me filtra por imágenes en este caso y
16:31
después logs es uno global qué es lo que hace Eh sí se puede se puede se puede
16:40
que en este caso tendrías que hacer eem a ver dónde está podes tener uno que
16:47
se llame eh eh No sé multer 1 multer 2 o o con un
16:54
nombre en específico y acá lo agregas a la par pero también si es que que quieren agregar
más imágenes hay una
17:00
forma de manipular lo que es multer no eh Y configurarlo de una forma distinta ahí podrían
investigar ahí por en
17:06
YouTube hay bastantes videos de multer que están buenos y se pueden manejar a Ray se
pueden traer múltiples archivos y
17:12
demás y guardarlos como ustedes quieran Pero bueno ya tenemos listo lo
17:19
que es el validate product Ahora nos queda probarlo Cómo sabemos si va a
17:26
funcionar todavía no sabemos así nos falta el quinto paso nos vamos a dónde
17:32
está o sigamos lo que es la ruta ver cuando el usuario apunta a create es
17:38
decir cuando hace cli en el botón del formulario de enviar primero acta este
17:43
midw guarda la imag siempre y cuando sea una imego Pasa este se fija si es que hay
17:51
errores o si todos los campos están bien en caso de que estén bien se guardan en
17:57
alguna parte de este midw pero
18:02
todavía no hace nada acá en el leore Así que ahora tenemos que ir al Store para
18:08
ver si podemos obtener esa información que se va guardando así que bueno vamos al
método Store hasta el momento
18:15
teníamos solamente esto no creamos el nuevo objeto pamos el nuevo objeto al
18:21
listado lo escribíamos y demás bueno ahora voy a preguntar primero si es que
18:26
hay errores hacem todo si es que no hay si no hay errores haceme todo eso Si es
18:31
que hay no hagas nada o no en realidad sí haceme algo pero primero preguntemos y recién
veamos Qué pasa pero bueno
18:40
primero vamos a intentar ver qué nos trae ese errors Así que error va a ser
18:46
validation validation result despés
18:57
validator
19:09
muy inteligente Así que se me trabó puude ser o
19:16
no era Ah Bien Hasta qué momento y 2
19:23
minutos cuando dijo buenas tardes
19:30
Sí hasta dónde llegamos a ver el cu estando elador eso ya vieron
19:38
esta parte no bien Bueno les mencionaba que eh se hizo el se hizo el Salto de
19:45
línea Solo cuando yo puse validation por ahí le metí un Tab y me auto importó
19:50
visual estudio esto que es justamente lo que vamos a necesitar de multer validation
19:56
resol bien y lo que vamos a validar el resultado en
20:03
Sí sería lo que viene del request Así que le vamos a indicar que lo que venga del request que
me lo guarden es errors
20:10
vamos a empezar haciendo unos conso log solamente cons el primero le vamos a llamar
20:16
errors error solamente pongamos un uno o algo así
20:24
errors y quiero que me muestre así en bruto eso vamos a hacer otro
20:32
consol porque no me acuerdo qué trae cada cosa así que vamos a hacer ahí una
20:37
Barrita como de separación y veamos qué pasa con errors maped que es un método
20:46
que viene incluido ahí en Express validator
20:57
er Lo acabamos de perder yo le clic al botón
21:07
aparecer a ver va tener que parar las
21:13
descargas no si será eso perch
21:20
que Aparentemente no no miren
21:26
cero Quiz tengo Cos en segundo plano descargando tantas
21:31
cosas cerremos este Battle en el que le sospecho que sea es Ahí
21:37
está bueno les mencionaba que simplemente estoy haciendo conso log para ver cómo
21:45
viene o cuál es la diferencia entre errors y Cuál es la diferencia entre errors
21:51
mapp así que bueno el proyecto creo que estaba levantado
21:56
como ven acá vamos al formulario descarguemos
22:03
vamos a enviarlo vacío mandemos todo vacío a ver qué pasa bien Aparentemente
22:09
me intento crear algo me creo un producto sin nada miren eso no está bien no estaría bueno
que el el administrador
22:18
de la página cree productos vacíos así que miren lo que pasó acá ya tengo los
22:23
dos cons vamos a hacerlo bastante grande para que se pueda ver Miren el primero
22:29
que se llamaba errors me trae o o sea el primer cons me
22:39
trae luego me trae una Ray acá
22:44
dentro y en el aray me trae todos los campos no
22:53
miren me trae name me trae price me trae y demás Pero Lo noto un poquito molesto
23:01
Para manipularlo no y luego con el maped miren del Indo que queda un objeto con
23:09
input name input price input description
23:14
así que de esa forma es mucho más sencillo utilizarlo No claro directamente invoco el
nombre y
23:22
punto punto mensaje por ejemplo como Ob literal claro es más fácil de
23:28
manipularlo ahí de forma individual porque si no acá para mostrar los errores tendríamos
que o para mostrarlo
23:33
en pantalla lo que tendríamos que hacer es eh un for each de este errors y que
23:40
me imprima los mensajes pero bueno hay que ver que esté bien el orden y todo eso es como
que ya es más
23:48
complicado así que bueno dónde quedó la pantalla bajemos un poco me parece que
23:54
nos quedamos con el map o quieren que empecemos a hacer con el errors y después lo
pasamos a map
24:00
para quede más lindo como prefieran usemos el error primero como para que vean Porque
creo Creo creo que van a
24:07
encontrar algo así con eso pero bueno En caso que lo encuentren en alguna parte de esa
forma les muestro Cómo se hace
24:14
bien Ahora sí preguntemos hay errores
24:19
errors está vacío y si es que está vacío haceme todo todo
24:27
eso que estab haciendo O sea si no hay errores haceme todo eso y si
24:33
no Mandame de nuevo el formulario y mostr en sí el error no así que
24:41
bueno r. render de la vista que nuestra vista
24:46
cómo se llamaba create for no lo copio a todo renderizar la vista
24:55
Uy renderizar la vista mándame un objeto con e errors errors que en este caso va
25:04
a ser errors solamente y mame también la información vieja así que lo vamos a llamar old
Data
25:11
puede ser old Solamente le vamos a mandar old Data Y eso va a ser todo lo
25:17
que venía en el body antes así que bueno ya lo tengo listo acá para manipular vamos al
25:25
formulario que en este caso vamos a acá tenemos lo que es el formulario no
25:32
nosotros podríamos crear acá una cajita muy fea que va a ser un dip que va a
25:40
tener eh A ver comoo este di va a
25:46
tener nada va a ser nada vamos a hacer un eh A ver cómo hacemos qué podemos
25:54
hacer Sí vamos a hacer un di para atrapar los errores
25:59
Class
26:05
errors Ah le pongos error solamente bien no
26:11
estoy con imaginación para inventar nombre graci así que bueno vamos a hacer una cajita
Solamente vamos a hacer un
26:17
for de esay con errores a cada elemento le voy a llamar
26:26
error y cada vez que pase por un error que me imprima una
26:31
ap que justamente me muestre ese mensaje así que vamos a hacer js output de
26:37
error punto cómo se llamaba
26:46
eh message justamente así que me vo a mostrar todos los los errores y creo que
26:53
esto no va a funcionar porque miren acá creo que no estoy no estoy enviando bien el objeto
porque
27:02
miren es un objeto y adentro tiene errors Pero bueno
27:08
probemos por las creo que ahí estoy equivocado me va a dar un error pero
27:13
bueno volvamos al formulario de creación u no me deja vamos al formulario
27:22
create me dice Ah bueno Ahí nos dice que er
27:28
puede ser que todavía no exista ningún error Así que primero preguntemos local existen
errores primero lo
27:39
errors no es la clase errors no nada que ver ya vamos a probar ejs If ya est
27:48
olvidando que estamos en
27:54
locals si es que existe que haga es for each me estaba olvidando El pequeño
28:00
detalle de que en la primera instancia no va a existir eso veamos ahí si soluciona el error
28:08
bien bueno por lo menos la la vista está si le damos a guardar producto me sale un error de
sintaxis
28:16
errors pun for each is not a function Así que era eh Me parece que es lo que
28:22
yo les decía no el objeto que vamos a mandar no es error solo porque error
28:28
solo es un objeto sino que sería error pun
28:34
errors no sé si les parece que lo llamemos de otra forma a este error y le llamamos result
para que quede que tenga
28:41
más sentido sí son
28:46
demasiad claro o sea que el validation result nos va a traer una variable que
28:53
bueno Nosotros le llamamos results y dentro de las cuales así en crudo nos trae
28:59
e un objeto result que tiene varias cosas y en las cuales nosotros necesitamos el arr
29:06
errors veamos ahí si funciona volvos hacia atrás le damos guardar producto y
29:12
de forma muy pequeña como ven acá me dice debes ingresar un nombre un precio y demás
pero no queda muy bonito la
29:19
vista no porque es una caja que está ahí metida quizás le podríamos dar estilo le
29:25
podríamos decir bueno que ese errors sea una caja que esté oculta Y
29:31
que cuando se genere el error me haga un pop up una ventanita flotante ahí que tape toda la
pantalla y que ahí me
29:37
muestre el error o algo así pero no es de mi agrado Así que esta era una forma
29:43
enviar errors así la otra opción era enviarlo de esta
29:53
forma results map quieren que les deje el código comentado con el ejemplo de la
30:00
otra forma o lo saco qué prefieren así le dejo una línea ahí
30:07
de le dejo una línea acá y abajo le hago otra línea como de ejemplo Qué opinan les dejo Ahí
30:14
comentado bueno por si las dudas a mí me gusta a veces probar cosas las dejo comentada
y
30:21
después cuando no me acuerdo de algo me vuelvo al repositorio y me fijo Cómo era este
cuando encuentro varias soluciones
30:28
de lo mismo no A eso me refiero así que bueno esto y en el caso del formulario
30:34
lo que habíamos agregado que no lo vamos a usar es este bloque de código Me
30:42
parece que veamos si no afecta en nada ese Comenta Uy si no afecta en
30:48
nada ahí está bueno ahí quedó normal no
30:54
y lo que sí tengo es eh bien Ya está listo está listo bueno
31:00
nosotros enviamos ahora a ver dónde estamos prod controller nosotros
31:06
enviamos result.map con el nombre de errors y ahora podemos acceder a
31:13
error name por ejemplo para manejar todo lo que son estas
31:19
propiedades pued manejar er price para enviar el mensaje de de ingresar un
31:25
precio y demás Así que bueno lo hagamos vamos a
31:30
nuevamente nuestro Index nuestro Perdón no nuestro Index nuestro product create
31:36
en este caso vamos a eh trabajar en Sí en cada uno de los
31:41
inputs que acá estaba nuestro formulario arranquemos por el
31:47
primero en este grupo Ven vamos a agregar un en este caso un If Djs js If
31:55
Y si existen errores punto errors
32:01
errors y también existen errores de
32:06
nombre errors name O sea si las dos cosas
32:11
coinciden imprime una p que diga no
32:18
sé js output output y que
32:24
diga errors punto mensaje porque en este caso queremos Mostrar solamente el mensaje y
32:31
vamos viendo si funciona no porque quizás no funciona así que
32:37
bueno Uy qué pasó se me cerró el escritorio no ahí
32:45
está for línea bueno Aparentemente no me deja hacer comentarios
32:53
acá Qué raro será por la
32:59
sintaxis control kc a
33:04
ver control kc kc claro es el mismo que estaba usando
33:12
Sí y si lo hago por línea
33:18
Ah no me está
33:24
dejando no eh aenta las líneas las etiquetas
33:33
html parear js
33:38
comment sería así Bueno probemos a ver si si la meto acá
33:47
esta y esta la pego acá abajo será que funciona No
33:53
no tengo que hacer línea por línea por es Ah no miren ahí parece que
34:00
funciona o no No sig igual
34:08
creo Claro esto Esto se hace línea por
34:14
línea sería Uy hagamos
34:20
control bueno o si no vamos a caer en el maldito chat PT para que nos comente las
34:25
cosas Pero bueno sería teóricamente sería algo así Si es que respeta la lo que es
34:34
el y el cierre sería así control c tuki tuki tuki
34:43
tuki este no este tampoco control B ahí prácticamente está
34:49
todo comentado Pero bueno no sé si si realmente está bien eso no
34:54
bueno Lamentablemente se va va este este locals con el forage así no perdamos
35:01
tiempo con eso listo Bueno ahí tenemos el formulario andando ya vamos a investigar cómo
se hace para agregar
35:07
comentarios ahí en bloque o en varias líneas para ejs si es que se puede
35:13
supongamos que bueno yo mando el formulario mal ahí ya efectivamente me sale debes
ingresar un nombre Obviamente
35:19
le tenemos que dar estilo ponerle que sea colorcito rojo que se alinee ha a un lado o algo
pero ya tenemos nuestro
35:27
input específico para detectar el error no o que me vaya mostrando así que bueno ahí
completo eso cuando
35:34
envío efectivamente Bueno ya se fue el error Pero bueno no me dejó crear el producto
porque siguen habiendo errores
35:41
No y algo que me estoy olvidando es a cada input agregar el valor
35:47
anterior que eso cómo lo haríamos en qué lugar va precargado la información que ya
35:55
tenía en cada input me
36:03
refiero Exactamente estaba leyendo el código
36:12
de justamente en el value de cada uno de los
36:18
inputs y viene desde el body por ejemplo este inut que era
36:25
el vamos a agregarle el valor
36:31
de js output y vamos a hacer un condicional
36:37
en este caso va a ser un ternario que si es que viene información vieja Data creo
36:44
que le habamos llamado y también u Y si en ese body en la primera
36:52
vez le cargamos información al por ejemplo nombre
36:57
Data name que me
37:02
imprima pregunta que me imprima ese valor datata name y si
37:10
no si no que me imprima un nul
37:16
estamos acá estamos haciendo unario preguntando si es que venía info
37:23
antes y también en esa info antes venía un valor que es name imprimime ese
37:31
nombre y si no dejalo vacío así que bueno pongamos miran

**********

0:01

imprimime ese nombre y si no déjalo vacío así que bueno pongamos

0:09
milanesa y como ven sigue persistiendo este valor Así que ahí tenemos

0:16

funcionando eso obviamente me faltan agregar todos los demás Campos Pero bueno eso lo van a hacer

0:23

ustedes Cuando quieran usarlo Pero bueno Ahí les voy agregando

0:28

finalmente Está bueno así como está esta estructura porque miren tienen cada grupo

0:36

de para su su input en específico no tienen un grupo un dip específico para lo que es

0:44

el input name luego tienen otro grupo que es específico para el precio y

0:49

demás Pero bueno veamos que si sigue funcionando no porque Bueno ahora vamos a crear un producto nuevo que se

0:54

llame aerógrafo el precio va a ser ser 100,000

1:02

supongamos el descuento va a ser de 5% la categoría va a ser en oferta y la

1:07

descripción va a ser aerógrafo x no sé y la imagen no tengo

1:16

se crea efectivamente el aerógrafo con todas las cositas Así que ahí tenemos funcionando nuestra

1:23

validación funciona perfecto como ven ya el

1:28

el el errors de los dos cons me salen vacíos no porque ya bueno en el último

1:34

en la última instancia no había errores así que bueno ya tranquilamente podemos comentar o eliminar o hacer lo

1:40

que queramos con estos consol les dejo los consol prácticamente para que lo

1:46

tengan ahí y puedan revisar ahí las cosas está buenísimo que se acostumbren a usar cons log una vez que ya no los

1:53
necesiten o lo comentan o lo eliminan lo ideal sería que lo eliminen Pero pero bueno este hasta que se vayan

1:59

acostumbrando en sí a consultar información Está bueno ahí usarlo no Y

2:04

agregarle quizás mensajitos así como para saber identificar cuál es uno y cuál es otro cuando tengamos que

2:10

comparar cosas muy parecidas no O quizás podemos decir eh No sé agregarle un

2:16

Stream ahí Que diga eh prueba de tal cosa y a la par le

2:22

pones el lo que queres probar no y te sirve ahí como para identificar dónde está ese conso porque a veces si lo

2:28

dejamos suelto no uno no sabe de De dónde viene eso bien y veamos si

2:33

funciona esto vamos a hacer un un delete y ahora me dice no

2:40

encuentro bien hay esto les había mostrado yo o no se acuerdan que había e Justamente

2:49

estaba el fs unlink que justamente servía para eliminar

2:57

imágenes o no o se dur o se

3:04

perdieron ahora intenté ejecutar este método y me tiró el error acá en el un

3:11

link Ven y me dice que bueno que no encuentra el directorio para

3:16

eliminar clase 31 public image default

3:28

bien se entiende esto se acuerdan de esto o

3:34

no vimos el el un link para para qué servía no me acuerdo no me acuerdo Bueno

3:42
creo que no lo vimos cre que será que lo agregué y les iba a comentar no

3:47

sé justamente bueno en este en el destroy lo que hacíamos era Buscar el producto que queríamos eliminar Perdón

3:55

separamos ese producto de que queríamos eliminar y lo volvíamos escribir al

4:00

Jason no con ese producto sin ese producto en sí Bueno luego agregamos

4:06

esto que se llama fs and link justamente para poder borrar la imagen porque si no

4:11

nos quedarían muchas imágenes sueltas ahí de productos que ya eliminamos bien Creo que creo que nos comentaste eso

4:18

profe lo habíamos visto pero así muy por encima acá bueno acá Tengo un problema que justo se abrió ahí el tema miren lo

4:26

que estaba intentando Bueno en realidad Acá está mal la ruta pero lo que estaba intentando hacer es borrar la imagen por

4:31

default Y eso está mal Ven y eso porque si yo borro la imagen por default todas

4:36

las demás imágenes que no tienen o todos los demás productos que no tienen imagen y estamos usando eso van a aparecer sin

4:43

imagen se entiend así que bueno acá tendría que preguntar primero si es que el producto es tal elimina eliminame la

4:51

imagen si no no buen si en realidad si la imágenes tal me la elimine si no

4:56

no la imagen no es la de default es exactamente y y lo haríamos así

5:04

Uy Por qué se me cambi el idioma Ahí está bueno si la imagen a ver

5:11

de todo esto punto join

5:16

Ay a ver cómo sería Ah así miren si product to

5:23
delete Recién veo que puse así detil a

5:28

ver arreglemos esto antes que que siga persistiendo el

5:34

error product to delete Ahí está bueno si producto delete

5:42

punto image es qué está pasando acá es igual igual a

5:49

o diferente en realidad diferente Cómo se llamaba la imagen por

5:58

default default cre que default solo no me parece que tenía algo

6:11

más bien hay que copiar específicamente para que puede hacer la validación bien

6:18

si es que es diferente a esto que me la elimine Igual acá está mal la

6:25

ruta bien minimicemos Un poco esto y veamos el error antes que se

6:30

vaya Comic Santiago lestero clase

6:36

31c etcétera barra public barra image barra default image bien coincide la

6:44

ruta realmente no clase 31 no está la carpeta

6:50

dentro del mid está por fuera no no en realidad la carpeta se

6:56

llama mid O sea la carpeta com 31 se llama Perdón clase 31 se llama clase 31

7:02

gu mw Ah bueno falta No tampoco porque porque public

7:09

está fuera de src pero este lo que nos está faltando miren está ingresando

7:15
image y luego está buscando nos falta Claro que entre el

7:20

directorio produ Así que tendría que entrar acá a prod se hizo gigante esto la ruta Pero

7:28

bueno en s lo que hace es este p. join es imprimirme el directorio donde está

7:35

parado en este caso sería en src

7:41

products luego hace un punto punto para volverse Hasta

7:47

src luego hace otro punto punto para volverse Hasta

7:52

middleware luego ingresa Uy ingresa al directorio public ingresa al directorio

7:59

image y luego ingresa al directorio product y luego ingresa al nombre de la

8:06

imagen para que podamos obtener obviamente esa ruta absoluta no

8:12

bien así que bueno supongamos que eh ese producto a ver sigue existiendo el producto ya no existe bien bueno veamos

8:19

algún producto en específico que queramos eliminar este no tiene imagen

8:24

no se debería eliminar o sea se va a eliminar el producto pero no se debería eliminar imagen Ahí está y supongamos

8:32

que ahora sí queremos eliminar uno con imagen nos record recordemos el nombre de la imagen así

8:40

podamos inspeccionar y a ver cómo se llamaba la imagen esta

8:47

Eh img camar nikon jpg bueno si funciona bien Esto se debería eliminar le dimos a

8:55

delete ya no aparece el producto ni la imagen y acá Uy

9:01
acá tengo tres escritorios acá eh en image ya no debe estar esa no debería Uh

9:09

Hay un montón pero bueno Supongo que Supongo

9:16

que ya no está no sé no la veo por ahí

9:21

Ah miren acá teníamos otro no Pero bueno no Aparentemente ya se eliminó Así que

9:27

ahí funcionó no Así que el unlink prácticamente está

9:34

funcionando perfecto Sí recuérdenme el concepto era si borro

9:41

el producto tengo que borrar la imagen así sería exactamente porque si no vamos a aborar el producto en Sí en el listado

9:48

de Jason pero la imagen va a seguir guardada en public v un montón de imágenes ahí Claro que no se van a

9:55

usar así que bueno ahí ya está a prueba de fallas me parece

10:02

este ese esa línea por ahí así que bueno estamos listos Si quieren hacemos un

10:08

break o ya directamente nos vamos a sala dividamos en salas y que ustedes se pongan a trabajar Prácticamente la

10:15

primera Consigna es hacer exactamente lo mismo que hicimos hace un momento del

10:20

middleware de de forma global y después el otro va a ser manipulando la query

10:28

params o un query String en realidad para que pregunte si es que viene un administrador que me muestre la vista y

10:34

si no no así que bueno Ese lo harían por a dónde están las rutas

10:42

deberían agregarlo no sea determinada ruta para ver si me deja entrar no que bueno no les voy a mostrar porque

10:48
si no estaría haciendo trampa Bueno vamos a salas les parece o quiere se

10:55

anima uno después del break a compartir la pantalla y lo intentamos resolver

11:00

Qué opinan ahí pongo grabar nuevamente Vamos a continuar con la

11:05

ejercitación recuerden Bueno ahí como dice Fran todos tienen que ayudar no A

11:12

ver quién va a ir leyendo La Consigna y lo va dictando va

11:17

diciendo No se olviden revisar todo la estructura del proyecto si que tiene instaladas las cosas el package Jon está

11:24

bien todo eso revisa

11:33

se me acaba de romper el micrófono en 3 2 1

11:40

Ah bueno escucho en el package Marcelo podrías ya agregarlo del lo del dev para

11:46

tenerlo listo

11:56

Bueno un mensaje ahí que me mandó le mand al frente creo que si hacemos así tal cual

12:04

prof hace rato tenemos que desinstalar el no y ponerlo

12:22

como ahí diría Bin

12:27

w y arriba en donde dice no s si

12:35

es ser no

12:52

serí

12:57
cu instal creo con la con la terminal en la

13:07

consol es creo que es anin con

13:17

ns no no no estoy escribiendo No es un instalamos creo Me parece que eso se

13:24

refiere n ahí está

13:42

así ahí se borró viste el pack Ahora hay

13:47

que instalarlo pero con el guion

13:57

d lo que sí no me acuerdo si venían

14:03

instalados los módulos o hay que instalar instal completo claro entonces

14:11

dale npm para que te los instal no sé si vena carpeta no pregunto me

14:20

acuerdo instalo todo te no lo veo instalado Así que bien

14:32

cómo sería profe O sea si si uno lo instala ya está instalado lo instala de vuelta no pasa nada no no no no habría

14:39

problema algunos quizás tienen la configuración a que se actualicen pero en este caso

14:44

no Por qué aparece eso de vulnerabilidades porque puede haber alguna librería que esté un poco

14:54

deprecada laón tambén ag eso por el tema de cuando que se minaba entonces habían

15:01

dependencias que lo que te hacían era que te minaban las instalas para minarte

15:07

entonces en base a eso fue que empezaron a agregar el tema de vulnerabilidades este justamente miren

15:14
acá están haciendo instalaciones de una versión en específico no y no le da es como que está bloqueado

15:20

y no le da el permiso a que se se vayan actualizando cuando nosotros este ejecutamos la instalación

15:30

bien Y ahora qué hago crearle carpeta mid que eso no está bien dentro de sabía

15:38

eso del minado de dentro de srs perfecto s a m Esa me la

15:48

comentó ayúdame Cómo se escribe porque no me acuerdo

15:54

m ot

16:03

l la

16:09

sy

16:20

ahora no sé si va a ser necesar instalar otras cosas como que me acuerdo haber leído puede

16:30

ser no sé si no haría falta Aparentemente

16:40

No qué más tenemos que tener un archivo que se llama userlock txt y otro que se

16:47

llama userlock js el userlock js va dentro de

16:54

midw users log Us en

17:01

singular Con la s l GS

17:07

J bien y el TX dónde iría eso lo decidimos la ruta cuando

17:14

vamos a guardar en el db creo no

17:19
Date deberí una

17:25

carpeta una carpeta Data Data no una carpeta creo que

17:33

decía ahí les pasé por el chat algo así buo info extra que justamente cuando en

17:40

el package Jon encuentren el simbolito ese que está le permite a npm cuando

17:46

hace la instalación aceptar parches compatibles si usan la flechita hacia

17:51

arriba o el simbolito hacia arriba permite actualizaciones compatibles hacia arriba hacia delante digamos y si

17:58

el asterisco permite cualquier versión eso es esos simbolitos que ven a veces

18:04

por ahí estos después más adelante vamos a ver

18:09

cómo se instala una determinada versión algún paquete Pero bueno no hace falta por el momento

18:15

profe eso significa que por ejemplo en debug en debug que tiene la el simbolito

18:21

ese significa que si yo quiero que me acepte cualquier versión le tengo asterisco Ah en vez del simbolito

18:27

exactamente y lo va a ir actualizando en Sí al paquete Pero bueno puede es complicado porque puede pasar que en la

18:33

actualización cambie la forma en que se usa no y y te termina rompiendo el código Así que hay que tener ojo también

18:39

con eso de de dejar todo abierto ahí a que se siga

18:44

actualizando bien entonces Hay que crear una carpeta log dentro de la carpeta

18:52

logs el final en srs Ajá bien

18:59
Perdón me mute de nuevo dentro de ese Ahí pones user

19:15

logs bien Bueno ahora

19:25

ayú vamos Dani estoy medio dormido

19:32

Marcelo bueno

19:37

Titi qué era un

19:42

midw lo que sí me acuerdo Marcel quees que exportarla

19:49

pued una aplicación que seuta antes del contenedor antes del

19:57

controlador poner ahí una función puedes poner

20:02

ahí Noa una

20:09

opción una opción era hacerlo anónimo a lo que es la función y simplemente hacer mod expor igual a esa función anónimo y

20:17

la otra opción era con el nombre de función y bueno después hac módulo pero

20:23

les recomend que lo hagan así más sencillo aso

20:28

Recuerden que tienen ahí el repositorio también de la comisión como para repasar o algo ahí ya lo subí los cambios y demás Pero

20:38

la idea es que entiendan también no no sea solamente copiar y pegar sino que se

20:43

entiendan los código Qué objetos contenían o teníamos

20:51

ahí para utilizar en en este tipo de de funciones con Express

20:57
bien el request response bien Ah

21:04

next bien bu Y qué va a hacer esto qué pedida lo Consigna

21:12

eh No sé no le las consignas lean lean las consignas los demás Ah ahí te digo

21:18

implementar un midw que nos permita autorizar el ingreso de usuarios administrador no el primero No ese es el

21:24

segundo Ah bien eh el primero dice usando de base

21:30

siguiente proyecto vamos a desarrollar un middleware para registrar el ingreso a cualquier ruta del sistema bien por lo

21:37

que dentro de la aplicación debemos crear un archivo de texto llamado userlock txt que deberá estar ubicado en

21:43

la carpeta logs y dentro de él deberemos registrar el ingreso a cualquier ruta

21:49

del sistema bien cada registro deberá quedar así el

21:54

usuario ingresó a la ruta y nombre del usar listo les parece que

22:01

primero armen el mensaje cómo va a quedar

22:13

bien y hacíamos con con esto

22:20

no que pongo el usuario ingreso a la

22:26

ruta los puntos

22:33

ot quea sería

22:39

punto verdad y ponemos la to eso

22:46
no y el Salto de línea El Salto de

22:52

línea ahí que

23:03

algo así puede ser

23:11

bueno ahora cómo lo hacemos para escribirlo ahí en

23:19

US usamos el

23:26

fs lo requerimos entero o cómo sí como ustedes prefieran lo podemos requerir

23:34

por parte nada más lo que usábamos que no con la

23:46

llavecita verdad Ahí va igual

23:56

a hable hable hable gente lo dejan solo

24:01

ahí estoy transpirando las Man todo Bueno listo ahí y cómo lo van a

24:09

usar no Marcelo aquí estamos bueno escucho

24:15

entonces escucho escribir no escucho hablar dijo

24:21

mero y bueno empiecen poniendo el nombre y y cuando abran el paréntesis hizo el estudio les va a ayudar en la sintaxis

24:27

ahí de cómo se usa Cómo se llama el método que acaban

24:32

de importar ap file Ahí está y Cuando abras el

24:39

paréntesis ya te va a tirar la sugerencia Ahí está primer argumento la ruta bien

24:47
eh invocamos va digo requerimos el pad o

24:56

bueno también puedes hacer como el de AR así Bueno qué van a usar de ahí

25:04

join

25:10

join estamos Sí ahí

25:15

va bien entonces join paréntesis

25:23

Ajá de name sí

25:31

Y ahora qué tien que hacer y ahora tienes

25:37

que busar en dónde está el archivo aj sería dy que escribirlo en

25:45

user.txt verdad Entonces sería dos puntos para ir atrás

25:54

digamos l

25:59

que es el nombre de nuestra carpeta bien y el archivo el archivo creo que es

26:16

así Ah perdón y ahora segundo

26:22

argumento y ahora s el mensaje que es lo que V a

26:30

inscribir por eso dentro del join o dentro del S No no por fuera porque el join es para hacer la ruta bien entre

26:38

los dos paréntesis sería msg verdad

26:44

Ajá muy bueno listo Entonces no F

26:53
bien bien bien bien bien ahí estamos

26:58

entonces portado tiene su siguiente para que continúe con la

27:04

pila y se supone que debería funcionar debería todavía no falta un pasito más

27:12

eh Y hay que ponerlo en el app.use Ahí va Lo tien que requerir en

27:18

el ya puede usarlo bien ese puntito blanco qué

27:25

hace que guardar marel

27:30

perd dónde en el

27:43

js buen ahora vamos para acá

27:48

ent Aquí al final lo ponemos

27:56

supongo

28:03

y cómo lo regier log igual

28:13

eh la rutia Dónde

28:20

está punto barra bien eh m muy bien

28:29

y el

28:38

bien log

28:43

entre así y creo que va con el con los paréntesis me

28:52
apece Qué pasa si va con los paréntesis en este momento al

28:59

explotemos que no explote nada en mi máquina por

29:07

favor antes que sigamos una consulta dice hacemos el require del user

29:15

ls porque no es necesario ponerle la extensión por no es necesario porque

29:22

estamos trabajando con módulos javascript que reconoce en

29:28

sí listo

29:33

listo ahí ahí está Y ahora cómo hacemos para que para

29:47

probar no grabaste app

29:54

perdón y a ver qué más dice no logro ver

30:01

si fíjate ahí lo puedes ocultar al de

30:09

zoom a la derecha tenes los tres puntitos y ahí te dice ocultar ventana

30:14

flotante creo que decía o algo así o algo de flotante o floating no sé ocult

30:23

panel ocultar panel video es Ah no no era ese O sí no no era

30:30

Entonces algo de ocultar ocultar nombre de anotadores mostrar panel de

30:35

video algo de flotante no Bueno lo dejamos hay probo

30:47

entonces igual creo que está con un error Cuál es el

30:53
error Reading 18 los paréntesis en el

31:03

log exactamente porque lo que está pasando Es que se está ejecutando bien

31:08

se levanta la aplicación y no cada vez que hacemos un pedido bien y a ver qué

31:13

más hay otro error o no sé a veces puede quedar cortado así y

31:21

bueno ten que probar ha una mano pero bueno Ahí tiene otro a ver qué dice

31:30

Lía 28

31:44

js Ah no está la ruta Ah no est configurada

31:52

Entonces es tramposo Play bueno No no estoy bien cómo se

32:00

llama Main en este

32:07

caso me gusta

32:12

rojs el archivo no es Main nada más Eh sí pero si es que lo vas a usar así

32:19

con Main Road tenes que cambiarlo en.js para que coincida no buenoo les

32:25

mencionaba que estaba bueno dejarlo así con ese nombre para que se pueda después distinguir el error cuando se genera uno

32:31

porque van a encontrar muchos Main y muchos Index en no modules y a veces nos hace confundir con alguno propio y lo

32:39

dejo con m Root por el momento lo dejemos así pero bueno lo ideal es que lo tengan ahí con sea un poquito más

32:45

específico no pero después hay que cambiarlo allá profe d estamos viendo recién Claro en el caso de que lo

32:51
hubiésemos dejado de esa forma Sí ahora no hace falta bien y cómo se configuraba

32:57

el roads Ah decía que que configuremos rutas y todo eso que queremos un par de

33:04

get pero lo hagamos con así con con r. solamente que mande mensajito nada

33:10

má bien portamos eh Express V a

33:25

necesitar bien después vas requerirlo con el ro digamos

33:34

o sea poner nombre

33:41

rter creo que er sin la

33:47

r con la e y ahí Creo que no más nombre

33:55

pero creo que estoy con

34:04

mayúscula bien ro de abajo punto G

34:11

bien Fíjate que no pong la r es con la e no

34:21

más y ahí todo lo que venga por la barra digamos y y después le V

34:29

que pasarlo el controlador bien el controlador obviamente no existe

34:36

el bueno no no controlador no hagan simplemente

34:42

ha porque si no estar Recuerden que el segundo argumento

34:49

segundo parámetros es una función

34:55
no Ah y no no primero tenes que

35:02

hacer acate que va el como la petición Ah Es un call el y dentro iría la

35:08

respuesta

35:14

en

35:20

bien y aquí y ahí iría lo que estabas poniendo

35:25

vos bueno

35:31

Eh cómo se llamaba

35:42

Index en este caso no hay un archivo Aparentemente hay un archivo Pero simplemente que hagamos r. de estás en

35:50

el Home otro que sea estás en lo que sea y así hagamos un tres o cuatro para que

35:55

podamos tener tres rutas nada más un nombre no más ponerle Mars claro

36:01

o sea lo que el r.en lo que te va a hacer es enviarte un mensaje que diga algo en este caso cuando accedamos al

36:08

Home que nos podría devolver o al al a nuestra barra digamos

36:16

raíz ahí bien

36:23

bu eh bueno y ahora quiero que repitan ese

36:28

mismo paso para no sé para varios menos para tres usuario

36:45

poner y no se olviden del Paso más importante Ahí también para que podamos utilizar ese router no y

36:54
exportar exactamente eh y otro no se oc product productos

37:03

productos

37:09

ahí profe la variable también se pue Llamar router como estaba poniendo al

37:14

principio que no como ustedes quieran pued llamar como sea Generalmente en la documentación lo

37:21

vo a encontrar como router Pero bueno igual funciona no

37:30

Okay está bien ahí sí ahí está bueno

37:35

guardamos entonces y ahora eh Hay que no sé si

37:40

estaba requerido en el app y ya debería de andar Bueno entonces hay que requerir

37:45

un el app js para creo que ya estí Sí ahí está est creo que haía dado

37:53

el error es rato sí ahí estaría creo eh

37:59

router nombre que le

38:06

pus Bueno entonces ahora prueben lo que es si funciona

38:17

es al navegador a ver si

38:24

va est está compartiendo solamente el visual no vemos nada bueno

38:33

paguen eh Dónde

38:42

está funciona funciona todavía no ah Están

38:49
viendo ahora ahora sí es la ra Ah por lo menos la ruta está y era usuario er buo

38:58

no Ajá siempre escribo usuario usuario no Sí así y el

39:06

otro era producto aot aot no era puesto no producto camb

39:18

producto ahí está ahí está buenísimo y funcionan todos y el log está guardando

39:24

el V ahí en ahí ahí

39:32

bien bueno tenemos listo eso nos

39:42

queda debe ser algo que debe estar puesto Ya no es cuando puse detalle

39:50

aquí del proyecto nuestro Pues sí puede ser que estés

39:57

tomando otr URL este Generalmente también par eh intentaste entrar que no

40:06

entraste ahí no no no no a este no es

40:14

es virus Ah no mentira misterioso bueno eso va a ser un

40:20

misterio que pensa que era era el Index html Pero bueno el fab es esto profe

40:26

pero bu si usted sí sabe qué Qué sería a ver eh A

40:33

ver pasa que

40:38

usaba esto el icono que se se pone aquí en la en la bien en el lugar de este en

40:47

sitio Ah ya ya ya listo sí no sé seguramente habría apretado ahí

40:53
por eso no bueno estamos entonces punto uno listo

40:58

nos quedó ya buen estamos con el tiempo justo ya en realidad pasados pero nos

41:04

quedó el segundo paso que prácticamente nos pedía que reciba por query si es que

41:09

era el nombre en sí de la persona este recuerdan Cómo se manipulaban las

41:14

queries vamos al navegador y con el signo de pregunta verdad exactamente

41:19

signo de pregunta el nombre de la query y el en realidad la la clave o el nombre

41:26

Sí y el valor con un igual no pero bueno como para tirarle ahí una pista más o menos así sería vamos al navegador y Y

41:34

bueno ya lo van a tener que resolver ustedes y se y se concatena con el ampersan verdad exactamente si teníamos más con

41:41

erson pero por ejemplo que sea productos Ajá signo de interrogación y

41:49

por ejemplo usuario Igual igual a el nombre

41:55

exactamente está aquí y poníamos pas igual

42:02

exactamente lo que sea la contraseña eso lo estás poniendo vos

42:13

ascar bien bueno entonces cómo van a obtener ese

42:20

query a través de era

42:28

recer exactamente del request van a tener ahí un objeto que se llama query y

42:33

en el query van a encontrar todos los los que bueno ustedes creen o usen que en este caso uno es usuario y el otro es

42:38
pas Pero bueno el de usuario simplemente va a funcionar con el de usuario ya cumplen con lo de la la ejercitación me

42:44

refiero así que bueno les va a tocar ahí jugar un poquito con eso no olviden que

42:49

tiene que ser un middleware Así que ustedes lo van a crear y preguntan ahí si coincide con el nombre x que está ahí

42:56

con permiso lo dejo entrar a la vista si no no lo que hemos hecho ahora lo puedes

43:03

pasar Marcelo por favor Eh sí sí ya lo gracias así que buenísimo Marcelo Muchas

43:09

gracias saco la compartición y estamos No ya nos pasamos un poquito los minutos

43:15

pero estuvo bueno porque ya pudieron resolverlo ahí y se entendió más o menos el repaso de hoy no va a quedar después

43:22

implementar Express validator bueno justamente ahí les queda la grabación para que puedan verlo y creo que no tengo nada más para

43:29

mencionar no se olviden de contestar la encuesta también que bueno eh suma un montón eso para nosotros

43:35

y nada más eso solamente no tengo nada más que tengan un buen inicio de semana

43:41

bueno prácticamente hoy ya es martes pero bueno que continúen así Igualmente prof

43:52

gracias

También podría gustarte