Bienvenidos sean a este post, hoy creamos nuestrto cliente.
En el post anterior ya establecimos a nuestro servidor, el cual basicamente hara toda la administracion de los mismos pero todavia no creamos la parte encargada de hacer las solicitudes y hoy nos centraremos en eso y para ello crearemos un cliente del tipo CLI (Interfaz de lineas de comandos), es decir que mediante una linea de comandos podremos crear/modificar/eliminar/visulizar los usuarios en nuestro server, para ello necesitaremos el codigo de nuestro post anterior, sino lo poseen les dejo un link para descargarlo:
Una vez descargado simplemente deben descargarlo y con eso tenemos nuestro proyecto funcionando, lo primero que haremos dentro del directorio users sera crear un nuevo archivo con el nombre de cli.mjs y le agregaremos el siguiente codigo:
cli.mjs
import { default as programa } from 'commander';
import { default as restify } from 'restify-clients';
import * as util from 'util';
var port_cliente;
var host_cliente;
var version_cliente = '*';
var prot_cliente;
var idauten = 'them';
var codigoaut = 'D4ED43C0-8BD6-4FE2-B358-7C0E230D11EF';
const cliente = (programa) => {
if (typeof process.env.PORT === 'string')
port_cliente = Number.parseInt(process.env.PORT);
if (typeof programa.PORT === 'string')
port_cliente = Number.parseInt(programa.PORT);
if (typeof programa.host === 'string') host_cliente = programa.host;
if (typeof programa.url === 'string') {
let purl = new URL(programa.url);
if (purl.host && purl.host !=='') host_cliente = purl.host;
if (purl.port && purl.port !=='') port_cliente = purl.port;
if (purl.protocol && purl.protocol !== '')
prot_cliente = purl.protocol;
}
let url_conectar = new URL('http://127.0.0.1:5858');
if (prot_cliente) url_conectar.protocol = prot_cliente;
if (host_cliente) url_conectar.host = host_cliente;
if (port_cliente) url_conectar.port = port_cliente;
let cliente = restify.createJsonClient({
url: url_conectar.href,
version: version_cliente
});
cliente.basicAuth(idauten, codigoaut);
return cliente;
}
Primero importaremos todos los modulos que necesitaremos, observen el primero que se llama commander, este sera el que nos permite hacer la «magia» de la linea de comandos porque nos permitira agregar los comandos, sus opciones y la accion que ejecutara pero de esto hablaremos en un momento, luego esta el modulo encargado de conectar mediante REST al servidor, y por ultimo la de util para usar principalmente el metodo inspect, despues declaramos/definimos una serie de variables con distintos propositos pero para la conexion:
- port_cliente, sera el puerto para conectarse
- host_cliente, sera el host para conectarse
- version_cliente, la version que usaremos y en este caso le pasamos el comodin para que sea cualquiera
- prot_cliente, el protocolo que debe usar para conectarse
- idauten, este es el usuario que usaremos con la funcion chequear para validar nuestra conexion
- codigoaut, es la clave que usaremos en conjunto con el id anterior
Despues definiremos una funcion llamada cliente, este recibira un objeto, luego tendremos una serie de condicionales donde verificaran algunos valores, el primero verifica si la variable de entorno de PORT es de tipo string, en caso de ser verdadero lo estableceremos a port_cliente, el siguiente condicional hace lo mismo pero el dato lo toma del objeto que informemos, el siguiente condicional tambien verifica si el valor de host del objeto es de tipo string y en caso de ser verdadero lo asignamos a host_cliente, el ultimo condicional verifica si url del objeto es de tipo string proceden a crear un nuevo objeto donde almacenaremos el valor de url, con este objeto iremos chequeando que los valores para host, port y protocol existen y los asignaremos a las variables correspondientes.
Suponiendo que se establecieron o no estos valores, crearemos un nuevo objeto con la conexion url predeterminada en caso no informar alguna, pero despues tenemos varios condicionales donde si algunos de los variables anteriores posee algun valor y en caso de ser asi se la asignamos al objeto anterior para sustituirlo, despues crearemos un objeto que sera el cliente que se conectara, para ello usaremos a restify y el metodo createJsonClient y le pasaremos el href del objeto que generamos anteriormente y la version, con nuestro objeto creado le aplicamos el metodo basicAuth para establecer el encabezado de autenticacion para todas las solicitudes HTTP, para finalmente devolver el objeto creado, con esto comando vamos a comenzar los primeros comandos y opciones para el cliente, agreguemos el siguiente segmento de codigo:
programa
.option('-p, --port <puerto>',
'Numero de Puerto del server si usa localhost')
.option('-h, --host <host>',
'Direccion de host si usa local')
.option('-u, --url <url>',
'URL de conexion al server si usamos uno remoto');
Observen que usamos el alias que le pusimos a commander, y agregaremos tres metodos llamados option para establecer las posibles opciones que podremos recibir, en este caso caso son los distintos valores que podemos establecer para conectarnos al sevidor, a su vez no pasamos solamente la sintaxis sino tambien una pequeña descripcion, en este momento si lo ejecutamos y usamos la opcion de ayuda se vera asi:
$ node cli.mjs --help
Usage: cli [options] [command]
Options:
-p, --port <puerto> Numero de Puerto del server si usa
localhost
-h, --host <host> Direccion de host si usa local
-u, --url <url> URL de conexion al server si usamos uno
remoto
--help display help for command
$
Volviendo a nuestro archivo y con las opciones de conexion del servidor establecidas pasemos a agregar la primera de la acciones:
programa
.command('add <usuario>')
.description('Agrega un usuario al servidor')
.option('--password <password>', 'Conntraseña del usuario')
.option('--apellido <apellido>', 'Apellido del usuario')
.option('--nombre <nombre>', 'Nombre del usuario')
.option('--email <email>', 'direccion de correo del usuario')
.action((usuario, cmdObj) => {
const subir = {
usuario: usuario,
clave: cmdObj.password,
proveedor: "local",
apellido: cmdObj.apellido,
nombre: cmdObj.nombre,
email: [],
foto: []
};
if (typeof cmdObj.email !== 'undefined')
subir.email.push(cmdObj.email);
cliente(programa).post('/crear', subir,
(err, req, res, obj) => {
if (err) console.error(err.stack);
else console.log(util.inspect(obj) + ' creado.');
});
});
En este caso sera para el comando para agregar un usuario donde primero pasamos el metodo command, para informar como es la sintaxis de este comando, despues pasamos una descripcion del comando, seguido a esto volvemos a usar option para poder agregar las distintas opciones que dispondremos como son la contraseña, nombre, apellido, y email, como estos datos son opcionales podemos omitirlo pero el unico obligatorio es el usuario que sera el id y el usuario en si, despues tenemos el metodo action donde tomaremos dos valores, el primero sera el usuario y el siguiente sera el encargado de tomar los que pasamos como opciones, eso lo notaran en el objeto que definimos posteriormente donde pasamos a cada campo de la tabla los valores que obtengamos pero a email y foto los dejamos en blanco, despues de esto tenemos un condicional donde verifica si email es distinto de undefined y en caso de ser verdadero agregue todas las direcciones que pasamos en la opcion email mediante push, recuerden que es un array para poder almacenar mas de un valor, ya con esto tenemos el objeto con todos los datos de nuestro usuario, lo siguiente sera llamar a la funcion cliente y le pasamos a programa, usamos el evento post y pasamos la identificacion crear para que se direccione a este escuchador.
Este es el encargado de crear los usuarios, sobre este hablamos en este post, pasamos el objeto con todos los datos del usuario para crearlo, despues tenemos cuatro argumentos, donde estaran los errores, solicitud, respuesta y el objeto que pasamos, despues en el condicional devolveremos el error si surge y en caso contrario informaremos que se creo, con esto comentado pasemos a agregar el siguiente comando:
programa
.command('find-or-create <usuario>')
.description('Busca un usuario sino lo encuentra lo agrega')
.option('--password <contraseña>', 'Contraseña para el usuario')
.option('--nombre <nombre>', 'Nombre del usuario')
.option('--apellido <apellido>', 'Apellido del usuario')
.option('--email <email>', 'Direccion de correo del usuario')
.action((usuario, cmdObj) => {
const subir = {
usuario: usuario,
clave: cmdObj.password,
proveedor: "local",
apellido: cmdObj.apellido,
nombre: cmdObj.nombre,
email: [],
foto: []
};
if (typeof cmdObj.email !== 'undefined')
subir.email.push(cmdObj.email);
cliente(programa).post('/buscar-o-crear', subir,
(err, req, res, obj) => {
if (err) console.error(err.stack);
else console.log('Se encontro o creo a ' +
util.inspect(obj));
});
});
Esta representa al escuchador que busca un usuario y sino lo encuentra lo crea, observen que es muy similar al anterior (son todos muy similares), donde pasaremos primero el comando, luego las opciones y la accion, en accion hacemos algo similar donde definiremos un objeto con todos los datos del usuario informados mediante el usuario y las opciones, y de forma similar al caso de agregar al usuario, lo mismo que el llamado a la funcion cliente, pero ahora usaremos el escuchador buscar-o-crear y es similar a lo visto anteriormente, pasemos a agregar el siguiente comando:
programa
.command('find <usuario>')
.description('Busca un usuario en el servidor')
.action((usuario, cmdObj) => {
cliente(programa).get(`/buscar/${usuario}`,
(err, req, res, obj) => {
if (err) console.error(err.stack);
else console.log("Encontrado " +
util.inspect(obj));
});
});
Este se encargara de buscar un usuario en particular, la estructura es similar pero mas sencilla, dado que no tendremos opciones, tampoco debemos crear el objeto con el usuario, la otra diferencia esta que en lugar de usar a post usa a get y pasamos un parametro, y de vuelta lo mismo para finalmente devolver todos los datos del usuario en caso de encontrarlo o el error en caso de no hacerlo, pasemos a agregar el siguiente comando:
programa
.command('list-users')
.description('Listar todos los usuarios del server')
.action((cmdObj) => {
cliente(programa).get('/listar',
(err, req, res, obj) => {
if (err) console.error(err.stack);
else console.log(obj);
});
});
Este comando se encargara de devolvernos el listado de todos los usuarios, la forma es la misma que los anteriores, no necesitamos ningun dato mas y aplicamos el evento listar para que haga el query para devolver todos los datos, tan simple como eso, pasemos a agregar el siguiente comando:
programa
.command('update <usuario>')
.description('Modifica o agrega un usuario del server')
.option('--password <contraseña>', 'Contraseña para el usuario')
.option('--nombre <nombre>', 'Nombre del usuario')
.option('--apellido <apellido>', 'Apellido del usuario')
.option('--email <email>', 'Direccion de correo del usuario')
.action((usuario, cmdObj) => {
const subir = {
usuario: usuario,
clave: cmdObj.password,
proveedor: "local",
apellido: cmdObj.apellido,
nombre: cmdObj.nombre,
email: [],
foto: []
};
if (typeof cmdObj.email !== 'undefined')
subir.email.push(cmdObj.email);
cliente(programa).post(`/cambiar/${usuario}`, subir,
(err, req, res, obj) => {
if (err) console.error(err.stack)
else console.log(util.inspect(obj) + 'Modificado');
});
});
Este se encargara de modificar los datos de un usuario ya existente, observen que volvemos a usar la misma estructura de los casos iniciales, inclusive el tema del objeto que contiene los nuevos datos del usuario, y en este caso usamos al escuchador encargado de cambiar y le pasamos el usuario que pasaremos con el comando, despues es todo muy similar, pasemos a agregar el siguiente comando:
programa
.command('del <usuario>')
.description('Elimina un usuario de la base')
.action((usuario, cmdObj) => {
cliente(programa).del(`/borrar/${usuario}`,
(err, req, res, obj) => {
if (err) console.log(err.stack);
else console.log('Se elimino - ' +
util.inspect(obj));
});
});
Este es el comando que usaremos para borrar los usuarios que le pasemos, y no es muy distinto a lo que vimos en todos los casos anteriores, pasemos a agregar el ultimo comando:
programa
.command('pwd-chk <usuario> <contraseña>')
.description('Permite chequear la contraseña de un usuario')
.action((usuario, clave, cmdObj) => {
cliente(programa).post('/chequear', {usuario, clave},
(err, req, res, obj) => {
if (err) console.log(err.stack);
else console.log(obj);
});
});
Este sera para aplicar el ultimo escuchador que agregamos en el servidor y sera para verificar la contraseña del usuario, en este caso la unica diferencia es que no utilizamos los datos de tipo usuario y cmdObj o subir sino que le pasaremos los valores de usuario clave que pasamos en el comando, despues es lo mismo que vinimos viendo hasta ahora, por ultimo al final del archivo debemos agregar la siguiente linea:
programa.parse(process.argv);
Esta es la que permitira que lo pasado como argumento en la linea de comandos sea interpretado correctamente, con esto comentado vamos a hacer un par de pruebas, y para ello debemos correr primero el servidor mediante el siguiente comando:
$ npm start
Con nuestro servidor corriendo debemos abrir otro terminal para poder realizar las pruebas, vamos a crear un usuario y para ello debemos ejecutar el siguiente comando:
$ node cli.mjs add --password clave --nombre Martin --apellido Miranda --email tinchicus@gmail.com tinchicus
Observen que pasamos primero el comando y antes del usuario agregamos todas las opciones para rematarlo con el usuario, si todo sale bien deben tener una salida semejante a esta:
$ node cli.mjs add --password clave --nombre Martin --apellido Miranda --email tinchicus@gmail.com tinchicus
{
id: 'tinchicus',
usuario: 'tinchicus',
proveedor: 'local',
apellido: 'Miranda',
nombre: 'Martin',
email: [ 'tinchicus@gmail.com' ],
foto: []
} creado.
$
Probemos ahora el siguiente comando:
$ node cli.mjs find-or-create etortore
Esta se encarga de buscar un usuario y si lo encuentra devuelve los datos pero sino lo encuentra procede a crearlo, veamos que paso con este caso:
$ node cli.mjs find-or-create etortore
Se encontro o creo a {
id: 'etortore',
usuario: 'etortore',
proveedor: 'local',
apellido: null,
nombre: null,
email: [],
foto: []
}
$
En este caso nos creo el usuario porque no existia en nuestra base pero vamos a proceder a agregar los datos faltantes y para ello usaremos el siguiente comando:
$ node cli.mjs update etortore --password palabra --nombre Enzo --apellido Tortore
En este caso agregamos los datos faltantes del momento de crearlo, veamos como fue la salida:
$ node cli.mjs update etortore --password palabra --nombre Enzo --apellido Tortore
{
id: 'etortore',
usuario: 'etortore',
proveedor: 'local',
apellido: 'Tortore',
nombre: 'Enzo',
email: [],
foto: []
}Modificado
$
Antes de utilizar el siguiente comando voy a ejecutar el siguiente comando:
$ node cli.mjs find-or-create prueba
Este generara el usuario de prueba, con esto realizado podemos ejecutar el siguiente comando:
$ node cli.mjs list-users
Este comando nos devolvera todos los usuarios de la tabla, veamos como es su salida:
$ node cli.mjs list-users
[
{
id: 'tinchicus',
usuario: 'tinchicus',
proveedor: 'local',
apellido: 'Miranda',
nombre: 'Martin',
email: [ 'tinchicus@gmail.com' ],
foto: []
},
{
id: 'etortore',
usuario: 'etortore',
proveedor: 'local',
apellido: 'Tortore',
nombre: 'Enzo',
email: [],
foto: []
},
{
id: 'prueba',
usuario: 'prueba',
proveedor: 'local',
apellido: null,
nombre: null,
email: [],
foto: []
}
]
$
Tenemos los tres usuarios que estuvimos trabajando hasta ahora pero para el siguiente borraremos el ultimo usuario que agregamos y para ello debemos usar el siguiente comando:
$ node cli.mjs del prueba
Este eliminara nuestro usuario y si volvemos a ejecutar el listado de usuarios se vera de la siguiente forma:
$ node cli.mjs list-users
[
{
id: 'tinchicus',
usuario: 'tinchicus',
proveedor: 'local',
apellido: 'Miranda',
nombre: 'Martin',
email: [ 'tinchicus@gmail.com' ],
foto: []
},
{
id: 'etortore',
usuario: 'etortore',
proveedor: 'local',
apellido: 'Tortore',
nombre: 'Enzo',
email: [],
foto: []
}
]
$
Ahora vamos a probar como es el comando para chequear las claves, ejecutemos el comando un par de veces y veamos como es la salida:
$ node cli.mjs pwd-chk tinchicus clave
{ check: true, usuario: 'tinchicus' }
$ node cli.mjs pwd-chk etortore clave
{ check: false, usuario: 'etortore', message: 'Clave incorrecta' }
$
Para ir finalizando vamos a ejecutar la opcion de ayuda para ver que nos muestra despues de haber agregado todos los comandos disponibles:
$ node cli.mjs --help
Usage: cli [options] [command]
Options:
-p, --port <puerto> Numero de Puerto del server si usa localhost
-h, --host <host> Direccion de host si usa local
-u, --url <url> URL de conexion al server si usamos uno remoto
--help display help for command
Commands:
add [options] <usuario> Agrega un usuario al servidor
find-or-create [options] <usuario> Busca un usuario sino lo encuentra lo agrega
find <usuario> Busca un usuario en el servidor
list-users Listar todos los usuarios del server
update [options] <usuario> Modifica o agrega un usuario del server
del <usuario> Elimina un usuario de la base
pwd-chk <usuario> <contraseña> Permite chequear la contraseña de un usuario
help [command] display help for command
$
Si lo comparamos como el usado al comienzo podemos ver como quedo mas completo, con esto ya tenemos nuestro cliente de tipo CLI para poder hacer el ABM de los usuarios, antes de terminar les dejo un link con todos los archivos del proyecto y los codigos trabajados en este post:
En resumen, hoy hemos creado un cliente para administrar los usuarios de nuestro servidor, donde mediante comandos de tipo CLI (command-line-interpreter) podemos realizar todas estas tareas, no solo hemos creado el cliente sino que tambien vimos algunas pruebas realizadas contra el servidor, espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
