laravel 5.6 crear api rest con autenticacion usando passport


Crear una nueva aplicacion laravel


composer create-project --prefer-dist laravel/laravel blog


Dentro de la carpeta del proyecto creado instalar Passport

composer require laravel/passport

Editar el archivo config/app.php

y en la seccion donde se registren providers agregar una nueva entrada para Passport
'providers' =>[
Laravel\Passport\PassportServiceProvider::class,
],


Crear la base de datos que usara la aplicacion y setear los datos de conexion en el archivo .env

Ejecutar la migracion
php artisan migrate

Instalar Passport para que genere los tokens de seguridad
php artisan passport:install

Editar app/User.php
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
  use HasApiTokens, Notifiable;


Editar app/Providers/AuthServiceProvider.php
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
        

Passport::routes(); 

//
    }
}

Editar config/auth.php en la seccion de guards cambiar la entrada para api/driver a passport

'guards' => [ 
        'web' => [ 
            'driver' => 'session', 
            'provider' => 'users', 
        ], 
        'api' => [ 
            'driver' => 'passport', 
            'provider' => 'users', 
        ], 
    ],

Crear la api route editando el archivo routes/api.php

Route::post('login', 'API\UserController@login');
Route::post('register', 'API\UserController@register');
Route::group(
 ['middleware' => 'auth:api'], 
 function(){
  Route::get('details', 'API\UserController@details');
 });


crear la carpeta API en app/Http/Controllers

en esa carpeta crear el controlador UserController.php

<?php

namespace App\Http\Controllers\API;

use Illuminate\Http\Request; 
use App\Http\Controllers\Controller; 
use App\User; 
use Illuminate\Support\Facades\Auth; 
use Validator;
class UserController extends Controller 
{
 public $successStatus = 200;
/** 
     * login api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function login(){ 
 if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){ 
  $user = Auth::user(); 
  $success['token'] =  $user->createToken('MyApp')-> accessToken; 
  return response()->json(['success' => $success], $this-> successStatus); 
 } 
 else{ 
  return response()->json(['error'=>'Unauthorised'], 401); 
 } 
}
/** 
     * Register api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function register(Request $request) 
{ 
 $validator = Validator::make($request->all(), [ 
  'name' => 'required', 
  'email' => 'required|email', 
  'password' => 'required', 
  'c_password' => 'required|same:password', 
 ]);
 if ($validator->fails()) { 
  return response()->json(['error'=>$validator->errors()], 401);            
 }
 $input = $request->all(); 
 $input['password'] = bcrypt($input['password']); 
 $user = User::create($input); 
 $success['token'] =  $user->createToken('MyApp')-> accessToken; 
 $success['name'] =  $user->name;
 return response()->json(['success'=>$success], $this-> successStatus); 
}
/** 
     * details api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function details() 
{ 
 $user = Auth::user(); 
 return response()->json(['success' => $user], $this-> successStatus); 
} 
}

Ya podemos probar la api rest:

la de creacion/registro de usuarios

POST http://localhost/authblog/public/api/register

Y en el body ( fom-data ) envio

name
email
password
c_password

el de login

POST http://localhost/authblog/public/api/login

Y en el body ( fom-data ) envio

email
password

que nos devolvera algo similar:

{
    "success": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImZjODRmMzhhZjg3MmNlZTM0ZDgyZGRlZjNkNDI3OWU0OGE3MjIzYmY5ZjY1ZDVkN2ZlOWNhN2ExNWQ5NGZhNWFiMDg0ZTM1ZmE3N2U4NjgzIn0.eyJhdWQiOiIxIiwianRpIjoiZmM4NGYzOGFmODcyY2VlMzRkODJkZGVmM2Q0Mjc5ZTQ4YTcyMjNiZjlmNjVkNWQ3ZmU5Y2E3YTE1ZDk0ZmE1YWIwODRlMzVmYTc3ZTg2ODMiLCJpYXQiOjE1MzQ2NDcwMDIsIm5iZiI6MTUzNDY0NzAwMiwiZXhwIjoxNTY2MTgzMDAyLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.FWOKWiOsWLv5oWrIWPKCsMRFd9k2DXMePgr6bWZRVwQqTj-8V5c5ZNfsntDehNnZ0mP0IWBgA9NtjFBeC-VUwsN4uowi3nd8LMINtkMhPa61mPXkem83hxA0t4ZO46dWWggq64kXCkwZz0CRkv99F4RRVd3G6_upKbMZy0U-t-G0GNC8uXs6OQsIGDoTGTAxdUSs7fbS4uC4TinYAirxibBpbXGRTE0Hxr4-ji5vKU0myHPPk9xg-6x4kHin6JVXvIU5QHkWJxYDXOaou0OF2znW8huG7L-s4G4zUmHbID6vc8ycIkdpGP2lFRaomyVtwtnQMze6YLCYEQtf28JfBaMyuejsPzj788Dv0ijK7BJmfc0zOgsuOqb3xkzgczAtmlJarwbJlEVHCH99tAP1iC75lNHw1lgo1_EcU9aRvRrmmGaEb4GIQdFqf7O5Hf5trmiFpszEVOGkGxQVe1acs_HIpv9ivUAkh5aPDczI2ZrH7WAXnyIcaO92OqX4ZbdTtpyk-J-ExXiNCjjfyg7bOsh3sXwZKO76hlpp1oPiAwbj1hrTND8Gz5_0nE37pqG0cu65m81VnwGezs3nOCnBkHsvQ6FiIdK_ViBOS9rnUaypwMCEjnJLimdNjI-jFZBJ1dUkws2GHlianISxegFq6pmBiBMtX0dZTJeEUu3je_M"
    }
}

el que trae los detalles de un usuario

GET http://localhost/authblog/public/api/details

en este caso debemos enviar en el header
Accept -> application/json
Authorization -> Bearer {{el token que se obtiene en el login}} 

que nos devolvera algo asi:

{
    "success": {
        "id": 1,
        "name": "ibazan",
        "email": "israelbazan76@gmail.com",
        "created_at": "2018-08-18 22:42:41",
        "updated_at": "2018-08-18 22:42:41"
    }
}





curso node leer y guardar en un archivo

estructura de proyecto:

db/data.json
por-hacer/por-hacer.php
app.js

/*********** por-hacer.php **********/

const fs = require('fs');

let listadoPorHacer=[];

const cargarDB = () =>{
try {
//
listadoPorHacer=require("../db/data.json");
} catch(e) {
// al inicio cuando el archivo esta vacio nos da una exception, entonces la variable
// la ponemos como una arreglo vacio
listadoPorHacer=[];
}


}

const crear=(descripcion)=>{

    cargarDB();

let porHacer = {
descripcion:descripcion,
completado:false
}

listadoPorHacer.push(porHacer);

guardarDB();

return porHacer;
}

const guardarDB=()=>{
let data=JSON.stringify(listadoPorHacer);
fs.writeFile('db/data.json', data, (err) => {
      if (err) throw new Error('No se pudo grabar',err);
     // console.log('The file has been saved!');
    });
}

const actualizar=(descripcion,completado=true)=>{

    cargarDB();

let index = listadoPorHacer.findIndex(tarea=>tarea.descripcion===descripcion);

if(index>=0){
listadoPorHacer[index].completado=completado;
    guardarDB();
        return true;
}


return false;
}

module.exports = {
crear, getListado, actualizar
}


/**************************   app.js ******************************/
const { crear, getListado, actualizar } = require('./por-hacer/por-hacer.js');


let comando =argv._[0];

switch (comando) {
case 'listar': let listado = getListado(); for(let elemento of listado){ console.log(elemento.descripcion +' estado: '+elemento.completado); } break; case 'crear': crear(argv.descripcion); break;
case 'actualizar':
console.log("actualizar");
break;
default:
console.log("comando no reconocido");
break;
}


vamos a agregarle la tarea de borrar entonces en app.js

case 'borrar':
    if(borrar(argv.descripcion,argv)){
    console.log('Borrado OK')
    }else{
    console.log("Fallo en el borrado");
}
break;

y en por-hacer.js

const borrar=(descripcion)=>{

    cargarDB();

let index = listadoPorHacer.findIndex(tarea=>tarea.descripcion===descripcion);

if(index>=0){
listadoPorHacer.splice(index,1);//elimina en la posicion index 1 elemento
    guardarDB();
        return true;
}


return false;
}
//recordar exportarla
module.exports = {
crear, getListado, actualizar, borrar
}

y en app.js
agregarla a la lista de funciones que necesito

const { crear, getListado, actualizar,borrar } = require('./por-hacer/por-hacer.js');

en yargs.js agregar la definicion de la tarea

.command('borrar','borra una tarea',{
    descripcion:descripcion
})


para ejecutar

node app.js borrar "nombre de tarea a borrar"

curso node guardar proyecto en github

en la consola y desde la carpeta del proyecto

escribimos

git init

luego creamos en la raiz creamos un archivo .gitignore

y listamos los archivos o carpetas que no queremos backupear
por ejemplo

*.txt
node_modules/

luego
git add .
git commit -m "commit inicial"

luego vamos a nuestra cuenta de github y creamos un New repository en donde se almacenaran los backups de nuestro proyecto, por ejemplo uno llamado "multiplicar-node"

volvemos a la consola y
seteamos la direccion que tomaremos como "origin"
git remote add origin https://github.com/israelbazan76/multiplicar-node.git

y luego enviamos los archivos a la rama master
git push -u origin master

podemos tambien escribir un archivo de readme describiendo el archivo.

esto lo hacemos creando un archivo en la raiz llamado README.md

(la extension md significa que es un archivo markdown..archivo de markado ligero 
con una sintaxis sencilla)

lo subimos
git add .
git commit -m "nuevo readme.md"
git push

listo, ahora cuando entremos a nuestro repositorio, veremos el archivo readme
interpretado.

https://github.com/israelbazan76/multiplicar-node




curso node yargs simplificar configuracion de comandos

la parte inicial del codigo la podemos separar en otro archivo y en el caso del ejemplo en el que estuvimos trabajando de crear y listar las tablas de multiplicar en el que los argumentos son los mismos estos se pueden tambien simplificar.

entonces podemos crear una carpeta config y dentro el archivo yargs.js

ahi adentro pondriamos

const opciones={
base:{
demand: true,
alias: 'b'
},
limite:{
alias:'l',
default:10
}
};

const argv=require('yargs')
.command('listar','imprime por consola la tabla de multiplicar',opciones)
.command('crear','crea un archivo con la tabla de multiplicar',opciones)
.help().argv;

module.exports = {
argv
}

y luego en el archivo de la aplicacion principal app.js

const argv=require('./config/yargs').argv;//asi solo tomamos argv para asignarlo a nuestra variable




curso node argumentos con yargs

seria interesante enviar a nuestra apliacacion argumentos por linea de comandos de una forma standar
algo asi:
[operacion] [nombre parametro] [valor parametro]

app listar --base 5

o incluso usando un alias

app listar -b 5

como hacemos esto facilmente? usando YArgs

lo buscamos en la pagina de npm
https://www.npmjs.com/package/yargs

y lo instalamos:

npm i yargs --save

esto hara que en nuestro archivo package.json
se agregue a la seccion de dependencias:

"dependencies": { "yargs": "^12.0.1" }


entonces ya podemos usar yargs en nuestra aplicacion
const argv=require('yargs') .command('listar','imprime por consola la tabla de multiplicar', { base:{ demand: true, alias: 'b' }, limite:{ alias:'l', default:10 } }).argv; console.log(argv.base); console.log(argv.limite);

en el codigo anterior estamos definiendo el command "listar" con 2 argumentos
base y limite, donde base es obligatorio y limite tiene un valor por default si
es que no se le asigna ninguno.

vamos a crear en nuestro multiplicar.js una function llamada listarTabla
en la que se le envie la base y el limite
y solo nos muestre el resultado por consola.

entonces nos quedaria asi

let listarTabla=(base,limite)=>{ return new Promise((resolve,reject)=>{ if(!Number(base)){ reject(`el valor introducido ${base} no es un numero`); return; } if(!Number(limite)){ reject(`el valor introducido ${limite} no es un numero`); return; } let data=''; for(let i = 1; i <= limite; i++){ data += ` ${base} x ${i} = ${base*i} \n`; } resolve(data); }); };

lo exportamos
module.exports = { crearArchivo,listarTabla }

y lo usamos en nuestra app principal

const { crearArchivolistarTabla } = require('./multiplicar');
let comando=argv._[0]; switch(comando){ case 'listar': listarTabla(argv.base,argv.limite) .then(data=>console.log(data)) .catch(e=>console.log(e)); break; case 'crear': crearArchivo(argv.base) .then(archivo=>console.log(`archivo creado: ${archivo}`)) .catch(e=>console.log(e)); break; default: console.log('el comando no existe'); }

curso node argumentos en linea de comando

process.argv es un arreglo que contiene los argumentos de linea de comando.
El primer elemento (process.argv[0]) contiene la ruta al ejecutable de node, el segundo elemento contiene el nombre del archivo javascript en ejecución. Los siguientes argumentos tienen los valores pasados por linea de comandos. .
process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`);
});
si en la consola ejecutamos:
args-by-console uno dos tres

obtendremos:
0: C:\Program Files\nodejs\node.exe 
1: c:\proyectos-node\03-bases-node\args-by-console.js
2: uno
3: dos
4: tres

curso node importar archivos file system


la documentacion de los archivos https://nodejs.org/dist/latest-v10.x/docs/api/fs.html
que se pueden importar que vienen ya en node.

const fs=require('fs');

let data='';
let base=2;

for(let i = 1; i <= 10; i++){
data += ` ${base} x ${i} = ${base*i} \n`;
}

fs.writeFile(`tabla-del-${base}.txt`, data, (err) => {
  if (err) throw err;
  console.log('The file has been saved!');
});

veamos ahora como importar archivos propios separando el proceso anterior de creacion de archivo escribiendolo en un archivo e importandolo desde otro:

creamos p.e: mutiplicar.js
donde tendremos


const fs=require('fs');



let crearArchivo=(base)=>{

    return new Promise((resolve,reject)=>{
     
      let data='';
  for(let i = 1; i <= 10; i++){
data += ` ${base} x ${i} = ${base*i} \n`;
  }

  fs.writeFile(`tabla-del-${base}.txt`, data, (err) => {
  if (err)
  reject(err);
  else
  resolve(`tabla-del-${base}.txt`);
});
     
    });

};
//aqui se definen las funciones globales que se quieren poner
//como disponibles a lo largo de la aplicacion
module.exports = {
crearArchivo
}


y lo llamamos desde app.js asi:

const { crearArchivo } = require('./multiplicar');
let base=6;

crearArchivo(base)
.then(archivo=>console.log(`archivo creado: ${archivo}`))
.catch(e => console.log(e));

vamos a agregar una validacion a nuestra funcion para que valide que la base sea un numero

al inicio de la Promise pondremos

if(!Number(base)){
      reject(`el valor introducido ${base} no es un numero`);
      return;//para que no continue ejecutando el resto de lineas
      }


linux ubuntu mint actualizar chrome

 desde una terminal: $ sudo apt update $ sudo apt install google-chrome-stable