Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI

on:
push:
branches: [main, develop]
pull_request:

jobs:
tests:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php: ['8.0', '8.1']

steps:
- uses: actions/checkout@v4

- name: Configurar PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mbstring, pdo_sqlite, bcmath, intl
coverage: none

- name: Cachear dependencias de Composer
uses: actions/cache@v4
with:
path: ~/.composer/cache
key: composer-${{ matrix.php }}-${{ hashFiles('composer.lock') }}

- name: Instalar dependencias
run: composer install --prefer-dist --no-interaction --no-progress

- name: Preparar entorno
run: |
cp .env.example .env
php artisan key:generate

- name: Lint de sintaxis
run: find app database routes tests -name '*.php' -print0 | xargs -0 -n1 php -l

- name: Pruebas
run: php artisan test
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Imagen de desarrollo: PHP 8.0 es la versión con la que se probó el proyecto.
FROM php:8.0-cli

RUN apt-get update && apt-get install -y --no-install-recommends \
git unzip libzip-dev libpng-dev libonig-dev curl gnupg ca-certificates \
&& docker-php-ext-install pdo_mysql zip bcmath \
&& curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

EXPOSE 8000

CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]
183 changes: 115 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,115 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>

# User App
<p>
Proyecto realizado para cumplir el ciclo básico de registro de usuarios (CRUD), donde el administrador pueda ingresar, realizar operaciones CRUD con los usuarios, el usuario registrado recibirá un mail de bienvenida, de igual forma el administrador recibirá un mail con el conteo de usuarios por país.
</p>

## Disposición técnica
<ul>
<li>Laravel 8</li>
<li>Blade</li>
<li>Tailwind css</li>
<li>Postgresql</li>
<li>Vue js</li>
<li>Inertia js</li>
<li>Git flow</li>
</ul>

## Instalación
<ul>
<li>Clonar proyecto o descargar como zip</li>
<li>Crear archivo .env tomando como base .env.example</li>
<li>Configurar credenciales de BD en archivo .env</li>
<li>Desde la linea de comandos:
<ul>
<li>composer install</li>
<li>npm install && npm run dev</li>
<li>php artisan key:generate</li>
<li>Configurar Base de datos en archivo .env</li>
<li>php artisan migrate --seed</li>
</ul>
</li>
</ul>

## Configuración email
Para el correcto funcionaminto del envío de emails, es necesario configurar las variable de entorno correspondientes de acuerdo al driver de su preferencia, para las pruebas se utilizó mailtrap.
Finalizada la configuración: php artisan config:cache

Parámetro de configuración email de administrador:
Para esta configuración se debe modificar el usuario con perfil de administrador, ya que ese email es el utilizado para enviar el mail de usuarios por pais.

## Credenciales de acceso

Usuario Administrador:
email: admin@userapp.com.co
clave: 12345678

Usuario Cliente:
Pueden ser registrados por el administrador sin límite alguno.

## Características principales puestas en práctica
<ul>
<li>
Metodología git flow, para control de versiones.
</li>
<li>
Variables de entorno, para conexion a BD y envío de correos.
</li>
<li>
Events y Listeners, para gestionar el envío de mails.
</li>
<li>
Migraciones, BD relacional, relaciones eloquent.
</li>
<li>
Frontend, Vue js - Inertia js
</li>
</ul>
# User App — panel de administración de usuarios (Laravel 8 + Inertia/Vue)

[![CI](https://github.com/briend17/user-app/actions/workflows/ci.yml/badge.svg)](https://github.com/briend17/user-app/actions/workflows/ci.yml)
![PHP](https://img.shields.io/badge/PHP-8.0%2B-777BB4)
![Laravel](https://img.shields.io/badge/Laravel-8-FF2D20)
![Vue](https://img.shields.io/badge/Vue-3-42B883)

Panel administrativo con el ciclo completo de gestión de usuarios: el
administrador da de alta, edita y elimina usuarios; el usuario creado recibe un
correo de bienvenida y el administrador un resumen con el conteo de usuarios por
país.

Es un proyecto pequeño a propósito. Lo que muestra no es el CRUD, sino cómo está
resuelto alrededor: **autorización por política, validación en Form Requests,
efectos secundarios desacoplados mediante eventos y correo fuera del ciclo de la
petición.**

---

## Cómo levantarlo

Con Docker (no necesita PHP ni MySQL instalados):

```bash
git clone https://github.com/briend17/user-app.git && cd user-app
cp .env.example .env
docker compose up -d
docker compose exec app composer install
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate --seed
docker compose exec app npm install && docker compose exec app npm run dev
```

La aplicación queda en <http://localhost:8000> y los correos capturados por
Mailhog en <http://localhost:8025>.

<details>
<summary>Instalación local sin Docker</summary>

Requiere PHP 8.0+, Composer, Node 16+ y MySQL 8.

```bash
cp .env.example .env
composer install
npm install && npm run dev
php artisan key:generate
php artisan migrate --seed
php artisan serve
```

</details>

### Credenciales de la semilla

| Perfil | Correo | Clave |
| --- | --- | --- |
| Administrador | `admin@userapp.com.co` | `12345678` |

Los usuarios cliente los crea el administrador desde el panel.

### Correo

Los envíos van en cola (`ShouldQueue`). En local, con `QUEUE_CONNECTION=sync` se
procesan al vuelo; en producción hace falta un worker:

```bash
php artisan queue:work
```

Con Docker, Mailhog captura todo el correo saliente sin configuración extra.

## Pruebas

```bash
php artisan test # o: docker compose exec app php artisan test
```

La suite corre sobre SQLite en memoria: no hace falta base de datos externa ni
conexión a internet. GitHub Actions la ejecuta en cada push y pull request.

---

## Decisiones técnicas

**El panel es de administración y lo dice el código.** Las rutas estaban tras
`auth` + `verified`, pero cualquier usuario autenticado podía listar, editar o
borrar a cualquier otro. `UserPolicy` (aplicada con `authorizeResource`) restringe
el panel al perfil administrador e impide que un administrador se borre a sí mismo
y deje el sistema sin acceso.

**Solo entra lo validado.** `User::create($request->all())` dejaba pasar cualquier
campo del formulario a Eloquent, incluido `password` en texto plano. Ahora se usa
`validated()`, y las reglas comprueban lo que dicen comprobar: `celular` valida
diez dígitos con `digits:10`, no un rango numérico como hacía `min:10|max:10`.

**El correo no bloquea la petición.** Los listeners implementan `ShouldQueue`. El
resumen por país se calcula con `withCount`, que sustituye a cargar en memoria
todos los usuarios de todos los países y lanzar además un `COUNT` por fila desde
la vista.

**Los datos de arranque son deterministas.** El seeder de países consultaba una
API externa con la verificación TLS desactivada: `migrate --seed` fallaba sin
conexión o en CI, y los identificadores fijos del seeder de usuarios dependían del
orden de esa respuesta. Ahora la lista es local y las relaciones se resuelven por
nombre.

**Los errores se registran, no se tragan.** El manejo original hacía
`catch (Exception $e)` dentro de un namespace, que resuelve a `App\...\Exception` y
por tanto no capturaba nada: la transacción nunca se revertía y el usuario recibía
una redirección de éxito aunque la operación hubiera fallado.

## Stack

Laravel 8 · PHP 8 · MySQL 8 · Vue 3 + Inertia.js · Tailwind CSS · PHPUnit ·
Docker Compose · GitHub Actions
Loading
Loading