En este «sprint» (o lo que sea), vamos a continuar con el desarrollo de dos características principales.
Primero comprobaremos que se puede iniciar sesión con un usuario, y que tiene acceso a ciertos permisos, luego continuaremos con la creación y edición de tarjetas de crédito asociadas a un usuario.
Índice
Previos
Después de los [pasos anteriores]({% post_url 2023-07-06-credit-logbook-app-1 %}), tenemos que agregar algunas cosas al app service provider, migrar nuestra base de datos, es decir agregar todos los cambios que agregamos a las migraciones, de manera estructurada y también editar algunas de nuestras variables de entorno.
App service provider
Primero cambiamos algunas cosas en el AppServiceProvider
, comenzamos
agregando la prevención de lazy
loading
en los modelos, para evitar algunos problemas de performance.
También cambiaremos una parte de la gramática del la conexión a la base de datos, particulamente el formato de la fecha, ya que por defecto no tenemos precisión de milisegundos.
Migraciones
Las migraciones son muy útiles, pues nos permiten realizar cambios en la base de datos de manera controlada.
Esta es una forma segura de «interactuar» con la base de datos, ya que existe una tabla particular que lleva el registro de las migraciones que ya se han ejecutado de acuerdo a su fecha y las migraciones ejecutadas no se repiten.
Además en caso de que una de nuestras migraciones salga mal, y necesitemos hacer rollback de esta, podemos hacerlo sencillamente y con un solo comando.
Puedes leer más acerca de las migraciones en la documentación oficial de Laravel.
Comenzamos creando la tabla de migraciones.
sail artisan migrate:install
Como ya definimos el esquema que queremos en la base de datos e incluso ya definimos algunas de las migraciones, no queda más que ejecutarlas en nuestro entorno local.
Utilizaremos la opción --step
para que podamos hacer rollback a cada
migración individualmente.
sail artisan migrate --step
Si todo va bien, la consola nos mostrará un error… 😥 y es porque olvidé algo
importante, por defecto las columnas uuid
en Laravel no son llaves primarias,
por lo que no se pueden usar como llaves foráneas en otra tabla, así que vamos
allá a corregir el desastre…
Ahora sí podemos ejecutar las migraciones, pero como algunas tablas ya fueron creadas, hay que destruirlas para crearlas de nuevo.
sail artisan migrate:fresh --step
Excelente, nuestras tablas ya han sido creadas.
Env
También cambiaremos algunas cosas de nuestro archivo .env
.
Por ejemplo el valor de APP_URL
así como la sesión, la queue y la caché, ya
que queremos usar redis y ya de paso queremos aumentar el tiempo de la sesión,
a… 3 días o sea 259200 segundos.
Los valores que cambiaremos quedan algo así:
APP_URL=http://laravel.test
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=259200
API
Para probar nuestra API utilizaremos Postman, y comenzaremos agregando los endpoints necesarios para registrar a un usuario.
Agregamos un environment ahí creamos la variable API_URL
y luego una
petición HTTP.
Si nuestro servidor está ejecutandose con sail, tenemos la url: laravel.test
,
como queremos poder acceder a ella desde nuestro entorno local debemos
instruirle a nuestra computadora como hacerlo.
Editamos el archivo: /etc/hosts
y agregamos la siguiente línea:
127.0.0.1 laravel.test localhost
Así nuestra computadora sabrá redirigir las peticiones a las urls:
laravel.test
y localhost
a sí misma. (A partir de ahora obviaremos el
dominio, pero debe estar en todas nuestras solicitudes).
Cookie CSRF
Primero queremos obtener la cookie csrf, para evitar algunos
ataques, y lo haremos con la url:
/sanctum/csrf-cookie
Esta nos devolverá una cookie llamada XSRF-TOKEN
, que se ve más o menos así:
eyJpdiI6IjVDY1NrKzN6YzNBNFJVe...MWUxNmM5IiwidGFnIjoiIn0%3D
, si nos fijamos
bien, la parte final está algo rara %3D
, y es porque antes de enviarla en un
header deberíamos decodificarla para urls con una función similar a
decodeURIComponent.
En nuestro caso, sabemos que %3D
es =
, así que lo sustituimos y agregaremos
a un header llamado X-XSRF-TOKEN
en cada una de nuestras llamadas
siguientes. Como ahora estamos probando con Postman, entonces hacemos algo así:
Usuario
Seguramente utilizaremos una SPA para este proyecto en futuras iteraciones, así que dejaremos que Sanctum utilice sesiones para autenticar a los usuarios por lo que estaremos haciendo uso de cookies.
Registro
Para registrarnos utilizaremos Fortify, y aunque ya hicimos algunos pasos, nos faltó agregar el proveedor de Fortify a nuestra lista de proveedores para la app, así que hacemos eso.
También corregimos una regla de nuestras validaciones 😅
Después podemos hacer la solicitud a la url: /register
. Agregamos los datos
necesarios al body de la solicitud y lo enviamos.
Si todo salió bien obtendremos una respuesta 201, y sabremos que nuestro usuario ha sido registrado en el sistema.
Logout
Probaremos el logout antes del login ya que cuando un usuario se registra,
automáticamente inicia sesión. Actualizamos la ruta home
en nuestra
configuración.
Vamos a guardar el X-XSRF-TOKEN
como una variable en Postman y luego hacemos
la petición a la url: /logout
. Si todo sale bien, obtendremos una respuesta
204 como esta.
Login
Ahora probamos con la ruta /login
. Y podremos ver algo así.
Como Sanctum utiliza las cookies para la autenticación, no debemos preocuparnos por tokens además del de csrf cuando hacemos una petición post, así que mientras usemos las cookies de sesión, estaremos loggeados.
Tarjetas de crédito
Rutas
Vamos a agregar las rutas para las tarjetas de credito en nuestra API, así que
en el archivo routes/web.php
colocamos lo siguiente:
Lo pondremos en web
y no en api
, porque consideramos que usaremos una SPA
así que queremos enviar cookies, pero luego veremos como replicar esto para usar
un token también.
Route::middleware(['auth:sanctum'])->prefix('api')->group(function () {
Route::prefix('v1')->group(function () {
Route::apiResources([
'credit-cards' => CreditCardController::class
], [
'parameters' => [
'credit-cards' => 'creditCard'
],
'shallow' => true
]);
});
});
Ahí estamos agrupando dentro de un middleware las versiones, y dentro de la
primera versión, agregamos un
apiResource
que sirve para registrar solamente las rutas que no tienen vistas asociadas.
También ponemos las opciones parameters
y shallow
, la primera es para
cambiar el casing de los parámetros y la segunda para hacer que las rutas se
colapsen cuando sea
posible.
Así debería quedar nuestra tabla de rutas para credit-cards
:
Método HTTP | URI | Nombre de ruta |
---|---|---|
GET | api/v1/credit-cards | credit-cards.index |
POST | api/v1/credit-cards | credit-cards.store |
GET | api/v1/credit-cards/{creditCard} | credit-cards.show |
PUT/PATCH | api/v1/credit-cards/{creditCard} | credit-cards.update |
DELETE | api/v1/credit-cards/{creditCard} | credit-cards.destroy |
Políticas
Ahora registramos las políticas, porque aunque Laravel tiene registro automático, nuestras políticas no están en el folder por defecto, por lo que tenemos que decirle donde están.
Las rutas y políticas quedan así:
Traducciones
El idioma por defecto de nuestra aplicación será ✨ español ✨ pero de todas formas vamos a agregar algunos archivos de traducción ya que nos servirán para estandarizar los mensajes y nombres de atributos.
Cambiamos el idioma por defecto en config/app.php
y luego publicamos los
archivos de traducción.
sail artisan lang:publish
Tenemos que copiar los archivos a una nueva carpeta es_MX
y entonces traducir
todo… 😩
Pero bueno, aquí estamos (lo hizo chat gpt 🤷🏽).
Luego agregamos las nuevas etiquetas.
Form requests
Vamos a utilizar form requests para validar los datos que llegan y saber si debemos guardarlos en la base de datos o solicitar correcciones al usuario…
Pero esto lo dejaremos para el siguiente sprint.