Actualizar README y PLAN con estado actual del sistema
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 16s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 16s
README.md: - Transformado en documentación completa del sistema de trazabilidad - Agregadas secciones: Modelo de Datos, API Endpoints, Base de Datos - Documentado estado de persistencia entre deploys - Agregado próximo objetivo: Visualización del Grafo - Actualizada estructura del proyecto - Ejemplos de uso y configuración PLAN_TRAZABILIDAD.md: - Agregada sección 'Estado Actual del Proyecto' al inicio - Lista de características completadas - Objetivo actual claramente definido: Visualización del Grafo - Tecnologías a considerar para implementación
This commit is contained in:
@@ -1,8 +1,44 @@
|
||||
# Plan de Trazabilidad de Lotes - Seguidor de Lotes
|
||||
|
||||
## Estado Actual del Proyecto
|
||||
|
||||
🌐 **Producción**: https://lotes.nucleoriofrio.com
|
||||
|
||||
### ✅ Completado
|
||||
|
||||
- [x] Modelo de base de datos (grafo DAG)
|
||||
- [x] Scripts de inicialización y seed con datos de ejemplo
|
||||
- [x] API REST completa (11 endpoints)
|
||||
- [x] Función recursiva de trazabilidad SQL
|
||||
- [x] Autenticación con Authentik Proxy
|
||||
- [x] CI/CD con Gitea Actions
|
||||
- [x] Despliegue automático con Docker Compose
|
||||
- [x] Persistencia de datos entre deploys
|
||||
- [x] Configuración automática de autenticación PostgreSQL
|
||||
- [x] Botones de prueba de API en frontend
|
||||
|
||||
### 🎯 Objetivo Actual: Visualización del Grafo
|
||||
|
||||
**Meta**: Implementar un componente visual que muestre el grafo de trazabilidad de forma interactiva.
|
||||
|
||||
**Requisitos**:
|
||||
- Visualizar el flujo completo de un lote desde origen hasta estado actual
|
||||
- Mostrar nodos (lotes) y aristas (operaciones)
|
||||
- Interactividad: zoom, pan, click en nodos
|
||||
- Metadatos al hacer hover
|
||||
- Indicadores visuales por tipo de operación
|
||||
|
||||
**Tecnologías a considerar**:
|
||||
- D3.js (máximo control, curva de aprendizaje)
|
||||
- vis.js (redes y grafos, fácil de usar)
|
||||
- Cytoscape.js (grafos complejos, buena performance)
|
||||
- ELK.js (layout automático de grafos)
|
||||
|
||||
---
|
||||
|
||||
## Descripción General
|
||||
|
||||
El **Sistema de Trazabilidad de Lotes** es una aplicación web diseñada para rastrear el flujo completo del café desde el ingreso de uva hasta el secado final. Implementa un **modelo de grafo** que permite representar operaciones complejas como:
|
||||
El **Sistema de Trazabilidad de Lotes** rastrea el flujo completo del café desde el ingreso de uva hasta el secado final. Implementa un **modelo de grafo (DAG)** que permite representar operaciones complejas:
|
||||
|
||||
- **División**: Un lote se divide en varios (ej: despulpado → primera, segunda, rechazos)
|
||||
- **Combinación**: Varios lotes se mezclan en uno (ej: varios reposos → un secado)
|
||||
|
||||
584
README.md
584
README.md
@@ -1,241 +1,331 @@
|
||||
# Seguidor de Lotes
|
||||
# Seguidor de Lotes - Sistema de Trazabilidad de Café
|
||||
|
||||
Aplicación Nuxt 4 para seguimiento y gestión de lotes, con autenticación mediante Authentik Proxy Outpost.
|
||||
Sistema completo de trazabilidad para café, desde ingreso de uva hasta secado final, implementando un modelo de grafo (DAG) para rastrear transformaciones, divisiones y combinaciones de lotes.
|
||||
|
||||
## Estructura del Proyecto
|
||||
🌐 **URL**: https://lotes.nucleoriofrio.com
|
||||
|
||||
## 🎯 Características Principales
|
||||
|
||||
- ✅ **Trazabilidad Completa**: Rastreo desde ingreso de uva hasta café secado
|
||||
- ✅ **Modelo de Grafo (DAG)**: Soporta divisiones (1→N), combinaciones (N→1) y transformaciones (1→1)
|
||||
- ✅ **API REST Completa**: 11 endpoints para gestión de lotes y operaciones
|
||||
- ✅ **Frontend Interactivo**: Interfaz con Nuxt UI para visualización y gestión
|
||||
- ✅ **Función Recursiva de Trazabilidad**: Consulta SQL que recorre todo el historial
|
||||
- ✅ **PostgreSQL sin ORM**: Queries directas con driver `pg`
|
||||
- ✅ **Autenticación Authentik**: Protección mediante Proxy Outpost
|
||||
- ✅ **CI/CD Automático**: Gitea Actions para build y deploy
|
||||
|
||||
## 📊 Modelo de Datos
|
||||
|
||||
### Estructura del Grafo
|
||||
|
||||
El sistema usa 3 tablas principales que forman un grafo dirigido acíclico (DAG):
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
|
||||
│ LOTES │◄─────│ OPERACION_LOTES │─────►│ OPERACIONES │
|
||||
│ │ │ │ │ │
|
||||
│ - id │ │ - operacion_id │ │ - id │
|
||||
│ - codigo │ │ - lote_id │ │ - tipo │
|
||||
│ - tipo │ │ - rol (in/out) │ │ - fecha │
|
||||
│ - cantidad │ │ - cantidad_kg │ │ - meta │
|
||||
└─────────────┘ └──────────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
### Tipos de Operaciones Soportadas
|
||||
|
||||
- **Ingreso**: Recepción de uva del productor
|
||||
- **Despulpado**: 1→3 (genera primera, segunda, rechazos)
|
||||
- **Oreado**: 1→1 (reducción de humedad en patio)
|
||||
- **Presecado**: 1→1 (reducción adicional de humedad)
|
||||
- **Reposo**: 1→1 (estabilización en bodega)
|
||||
- **Secado**: N→1 (combinación de lotes para secado final)
|
||||
- **Ajustes**: Corrección de mermas o tipos
|
||||
|
||||
### Ejemplo de Flujo
|
||||
|
||||
```
|
||||
UVA-001 (2086kg)
|
||||
│
|
||||
├─[Despulpado]─┬─► PRIM-001 (1500kg)
|
||||
│ ├─► SEG-001 (400kg)
|
||||
│ └─► RECH-001 (150kg)
|
||||
│
|
||||
└─[Oreado]────► ORE-001 (1500kg)
|
||||
│
|
||||
├─[Ajuste merma]────► ORE-001A (1480kg)
|
||||
│
|
||||
├─[Ajuste tipo]─────► PRE-001 (1480kg)
|
||||
│
|
||||
└─[Reposo]──────────► REP-001 (1480kg)
|
||||
│
|
||||
├─[Secado]─► SEC-001 (2000kg)
|
||||
│
|
||||
REP-002 (520kg)
|
||||
```
|
||||
|
||||
## 🚀 Inicio Rápido
|
||||
|
||||
### Requisitos Previos
|
||||
|
||||
- Docker y Docker Compose
|
||||
- Gitea con Actions habilitado
|
||||
- Traefik con red `traefik-network`
|
||||
- Authentik con Proxy Outpost configurado
|
||||
|
||||
### Despliegue Automático
|
||||
|
||||
1. **Fork/Clone del repositorio** en tu Gitea
|
||||
|
||||
2. **Configurar variables en Gitea** (`Settings > Actions`):
|
||||
|
||||
**Secrets:**
|
||||
- `REGISTRY_USERNAME` - Usuario del registro Docker
|
||||
- `REGISTRY_PASSWORD` - Contraseña del registro
|
||||
- `POSTGRES_PASSWORD` - Contraseña de PostgreSQL
|
||||
|
||||
**Variables:**
|
||||
- `REGISTRY_URL` - `gitea.nucleoriofrio.com`
|
||||
- `APP_NAME` - `lotes`
|
||||
- `APP_DOMAIN` - `lotes.nucleoriofrio.com`
|
||||
- `NUXT_PUBLIC_APP_URL` - `https://lotes.nucleoriofrio.com`
|
||||
- `POSTGRES_USER` - `seguidor`
|
||||
- `POSTGRES_DB` - `seguidor_lotes`
|
||||
|
||||
3. **Push al repositorio** - El workflow automáticamente:
|
||||
- Construye la imagen Docker
|
||||
- Sube la imagen al registro
|
||||
- Despliega con docker-compose
|
||||
- Inicializa PostgreSQL (solo primera vez)
|
||||
- Carga datos de ejemplo (solo primera vez)
|
||||
|
||||
## 📁 Estructura del Proyecto
|
||||
|
||||
```
|
||||
.
|
||||
├── nuxt4/ # Aplicación Nuxt 4
|
||||
├── docker-compose.yml # Configuración de despliegue
|
||||
└── .gitea/ # Gitea Actions CI/CD
|
||||
├── nuxt4/
|
||||
│ ├── app/
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── lotes/ # Componentes de lotes
|
||||
│ │ │ ├── operaciones/ # Componentes de operaciones
|
||||
│ │ │ └── auth/ # Componentes de autenticación
|
||||
│ │ ├── composables/
|
||||
│ │ │ ├── useLotes.ts # Lógica de negocio
|
||||
│ │ │ └── useAuthentik.ts # Autenticación
|
||||
│ │ └── app.vue # Aplicación principal
|
||||
│ ├── server/
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── lotes/ # Endpoints de lotes (6)
|
||||
│ │ │ └── operaciones/ # Endpoints de operaciones (3)
|
||||
│ │ ├── utils/
|
||||
│ │ │ ├── db.ts # Pool de PostgreSQL
|
||||
│ │ │ └── queries.ts # Funciones SQL
|
||||
│ │ └── database/
|
||||
│ │ ├── 00_configure_auth.sh # Config autenticación
|
||||
│ │ ├── 01_schema.sql # Esquema DB
|
||||
│ │ └── 02_seed.sql # Datos de ejemplo
|
||||
│ └── package.json
|
||||
├── docker-compose.yml # Servicios (app + postgres)
|
||||
├── .gitea/workflows/
|
||||
│ └── build-and-deploy.yml # CI/CD
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Características
|
||||
## 🔌 API Endpoints
|
||||
|
||||
- ✅ Nuxt 4
|
||||
- ✅ Autenticación con Authentik Proxy Outpost
|
||||
- ✅ Docker y Docker Compose
|
||||
- ✅ CI/CD con Gitea Actions
|
||||
- ✅ Traefik para proxy reverso y SSL
|
||||
- ✅ Claude Code hooks para monitoreo de Actions
|
||||
- ✅ Sin configuración OAuth necesaria (todo manejado por el proxy)
|
||||
### Lotes
|
||||
|
||||
## Desarrollo Local
|
||||
- `GET /api/lotes` - Listar lotes (con filtros)
|
||||
- `POST /api/lotes` - Crear lote
|
||||
- `GET /api/lotes/:id` - Obtener lote específico
|
||||
- `PATCH /api/lotes/:id` - Actualizar lote
|
||||
- `DELETE /api/lotes/:id` - Eliminar lote
|
||||
- `GET /api/lotes/:id/trazabilidad` - Obtener trazabilidad completa
|
||||
|
||||
### Operaciones
|
||||
|
||||
- `GET /api/operaciones` - Listar operaciones
|
||||
- `POST /api/operaciones` - Crear operación con lotes
|
||||
- `GET /api/operaciones/:id` - Obtener operación específica
|
||||
|
||||
### Ejemplo de Respuesta - Trazabilidad
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"historial": [
|
||||
{
|
||||
"lote_id": "...",
|
||||
"codigo": "SEC-001",
|
||||
"tipo": "secado",
|
||||
"profundidad": 0,
|
||||
"operacion_tipo": "secado",
|
||||
"fecha_operacion": "2025-11-20T01:12:19.489Z"
|
||||
},
|
||||
// ... historial completo hasta origen
|
||||
],
|
||||
"estadisticas": {
|
||||
"total_ancestros": 7,
|
||||
"profundidad_maxima": 6,
|
||||
"kg_iniciales": "2086.00"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🗄️ Base de Datos
|
||||
|
||||
### Persistencia
|
||||
|
||||
- ✅ **Los datos persisten entre deploys** (volumen Docker `lotes_postgres_data`)
|
||||
- ✅ Scripts de inicialización solo se ejecutan si no existen tablas
|
||||
- ✅ Configuración de autenticación (md5) se aplica automáticamente
|
||||
|
||||
### Reiniciar BD a Estado Inicial
|
||||
|
||||
Para volver a los datos de ejemplo:
|
||||
|
||||
```bash
|
||||
# Detener y eliminar volumen
|
||||
docker compose --project-name lotes down -v
|
||||
|
||||
# Próximo deploy reinicializará todo
|
||||
git commit --allow-empty -m "Trigger redeploy" && git push
|
||||
```
|
||||
|
||||
### Consultas Útiles
|
||||
|
||||
```sql
|
||||
-- Ver todos los lotes
|
||||
SELECT * FROM lotes ORDER BY fecha_creado DESC;
|
||||
|
||||
-- Ver trazabilidad completa de un lote
|
||||
SELECT * FROM get_trazabilidad('id-del-lote');
|
||||
|
||||
-- Ver estadísticas de un lote
|
||||
SELECT * FROM get_estadisticas_lote('id-del-lote');
|
||||
```
|
||||
|
||||
## 🎨 Frontend
|
||||
|
||||
### Tecnologías
|
||||
|
||||
- **Nuxt 4** - Framework Vue.js
|
||||
- **Nuxt UI** - Componentes basados en Tailwind
|
||||
- **TypeScript** - Tipado estático
|
||||
|
||||
### Componentes Principales
|
||||
|
||||
- **LotesTable** - Tabla con filtros y acciones
|
||||
- **LoteForm** - Formulario crear/editar lote
|
||||
- **TrazabilidadTree** - Árbol de trazabilidad con estadísticas
|
||||
- **OperacionForm** - Wizard de 3 pasos para crear operaciones
|
||||
|
||||
### Modo Debug
|
||||
|
||||
El sistema incluye botones de prueba para verificar la API:
|
||||
|
||||
1. Abre https://lotes.nucleoriofrio.com
|
||||
2. Abre consola del navegador (F12)
|
||||
3. Usa los botones "Probar API"
|
||||
4. Verifica resultados en consola
|
||||
|
||||
## 🔐 Autenticación
|
||||
|
||||
Sistema protegido con Authentik Proxy Outpost:
|
||||
|
||||
- **Forward Auth**: Authentik intercepta todas las peticiones
|
||||
- **Headers automáticos**: Usuario inyectado en cada request SSR
|
||||
- **Sin OAuth**: No requiere configuración OAuth en la app
|
||||
- **Rutas públicas**: PWA assets accesibles sin auth
|
||||
|
||||
Ver configuración detallada en la sección de Traefik al final del README.
|
||||
|
||||
## 🛠️ Desarrollo Local
|
||||
|
||||
**Nota**: El desarrollo local tiene limitaciones debido a la dependencia de Authentik Proxy.
|
||||
|
||||
### Opción 1: Desarrollo con PostgreSQL local
|
||||
|
||||
```bash
|
||||
cd nuxt4
|
||||
npm install
|
||||
|
||||
# Configurar PostgreSQL local
|
||||
export POSTGRES_USER=seguidor
|
||||
export POSTGRES_PASSWORD=seguidor_password
|
||||
export POSTGRES_DB=seguidor_lotes
|
||||
export POSTGRES_HOST=localhost
|
||||
|
||||
# Ejecutar scripts SQL
|
||||
psql -U seguidor -d seguidor_lotes < server/database/01_schema.sql
|
||||
psql -U seguidor -d seguidor_lotes < server/database/02_seed.sql
|
||||
|
||||
# Iniciar dev server
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Claude Code Hooks
|
||||
### Opción 2: Desarrollo contra servidor
|
||||
|
||||
Este proyecto incluye hooks de Claude Code para monitorear automáticamente las Gitea Actions.
|
||||
|
||||
### Configuración Rápida:
|
||||
|
||||
1. **Crear token de Gitea:**
|
||||
- Ve a tu instancia de Gitea → Settings → Applications
|
||||
- Genera un token con permisos `repo`
|
||||
|
||||
2. **Configurar token:**
|
||||
```bash
|
||||
echo "export GITEA_TOKEN='tu_token_aqui'" >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
cd nuxt4
|
||||
npm install
|
||||
|
||||
# Apuntar a BD de producción
|
||||
export POSTGRES_HOST=server.interno.com
|
||||
export POSTGRES_PORT=5432
|
||||
# ... resto de variables
|
||||
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **Listo!** Cuando Claude Code haga `git push`, automáticamente:
|
||||
- Monitoreará la Gitea Action
|
||||
- Te notificará cuando termine con información detallada
|
||||
- Te mostrará un link directo a los logs
|
||||
## 📈 Próximos Pasos
|
||||
|
||||
📖 Ver documentación completa en [`.claude/hooks/README.md`](.claude/hooks/README.md)
|
||||
### Objetivo Actual: Visualización del Grafo
|
||||
|
||||
## Chrome DevTools MCP
|
||||
**Meta**: Mostrar correctamente el grafo de trazabilidad creado con los datos de ejemplo.
|
||||
|
||||
Este proyecto está configurado para usar su propia instancia de Chrome con debugging remoto, permitiendo múltiples proyectos con navegadores independientes.
|
||||
**Tareas pendientes**:
|
||||
- [ ] Componente de visualización de grafo (D3.js, vis.js, o similar)
|
||||
- [ ] Layout de árbol o grafo dirigido
|
||||
- [ ] Interactividad (zoom, pan, click en nodos)
|
||||
- [ ] Mostrar metadatos al hacer hover
|
||||
- [ ] Indicadores visuales de tipos de operación
|
||||
|
||||
### Inicio Rápido:
|
||||
### Mejoras Futuras
|
||||
|
||||
1. **Iniciar el navegador del proyecto:**
|
||||
```bash
|
||||
./start-browser.sh
|
||||
```
|
||||
- [ ] Exportar trazabilidad a PDF
|
||||
- [ ] Búsqueda avanzada de lotes
|
||||
- [ ] Dashboard con estadísticas
|
||||
- [ ] Alertas de mermas excesivas
|
||||
- [ ] Integración con básculas IoT
|
||||
- [ ] App móvil con PWA
|
||||
- [ ] Reportes personalizables
|
||||
|
||||
2. **Configurar MCP en Claude Code** (solo primera vez):
|
||||
- Editá `~/.config/claude-code/config.json`
|
||||
- Agregá la configuración del navegador (puerto 9235)
|
||||
## 📚 Documentación Adicional
|
||||
|
||||
3. **Reiniciar Claude Code** para aplicar cambios
|
||||
- [PLAN_TRAZABILIDAD.md](PLAN_TRAZABILIDAD.md) - Plan detallado del sistema
|
||||
- [nuxt4/server/database/README.md](nuxt4/server/database/README.md) - Documentación de BD
|
||||
- [.claude/hooks/README.md](.claude/hooks/README.md) - Gitea Actions Hooks
|
||||
- [.claude/CHROME_SETUP.md](.claude/CHROME_SETUP.md) - Chrome DevTools MCP
|
||||
|
||||
📖 Ver documentación completa en [`.claude/CHROME_SETUP.md`](.claude/CHROME_SETUP.md)
|
||||
---
|
||||
|
||||
## Arquitectura de Componentes
|
||||
## 🔧 Configuración de Traefik y Authentik
|
||||
|
||||
### Componentes de Autenticación
|
||||
|
||||
La aplicación utiliza componentes Vue modulares para manejar la autenticación:
|
||||
|
||||
#### 1. **UserAvatar** (`app/components/auth/UserAvatar.vue`)
|
||||
- Muestra el avatar del usuario (generado por UI Avatars)
|
||||
- Información básica: nombre/username, email y UID
|
||||
- Se renderiza solo cuando el usuario está autenticado
|
||||
|
||||
#### 2. **UserMetadata** (`app/components/auth/UserMetadata.vue`)
|
||||
- Card detallada con todos los metadatos del usuario
|
||||
- Muestra: username, email, nombre completo, UID y grupos
|
||||
- Incluye badges para visualizar los grupos del usuario
|
||||
|
||||
#### 3. **Botones de Acción** (componentes individuales)
|
||||
Cada botón es un componente independiente con su propia lógica:
|
||||
|
||||
- **SessionStatusButton**: Verifica el estado de la sesión contra Authentik
|
||||
- Hace una petición a `/api/auth/status`
|
||||
- Muestra notificaciones toast con el resultado
|
||||
- Maneja casos offline y errores de conexión
|
||||
|
||||
- **ProfileButton**: Redirige al perfil de usuario en Authentik
|
||||
- Abre el panel de usuario de Authentik en nueva pestaña
|
||||
- URL: `{authentikUrl}/if/user/`
|
||||
|
||||
- **LogoutButton**: Cierra sesión en Authentik
|
||||
- Invalida la sesión en todas las aplicaciones
|
||||
- Redirige a: `{authentikUrl}/flows/-/default/invalidation/`
|
||||
|
||||
- **LoginButton**: Fuerza re-autenticación
|
||||
- Recarga la página para activar el flujo de login de Authentik
|
||||
|
||||
### Composable `useAuthentik()`
|
||||
|
||||
Composable centralizado para manejar autenticación (`app/composables/useAuthentik.ts`):
|
||||
|
||||
**Funcionalidades:**
|
||||
- Lee headers de Authentik en el servidor (SSR)
|
||||
- Almacena información del usuario en `useState` (compartido entre cliente/servidor)
|
||||
- Proporciona funciones reactivas: `user`, `isAuthenticated`
|
||||
- Métodos: `logout()`, `goToProfile()`, `checkSessionStatus()`
|
||||
|
||||
**Headers leídos del Proxy:**
|
||||
```typescript
|
||||
X-authentik-username // Nombre de usuario
|
||||
X-authentik-email // Email
|
||||
X-authentik-name // Nombre completo
|
||||
X-authentik-groups // Grupos (separados por |)
|
||||
X-authentik-uid // ID único del usuario
|
||||
```
|
||||
|
||||
## Despliegue
|
||||
|
||||
El proyecto incluye Gitea Actions que automáticamente:
|
||||
1. Construye la imagen Docker
|
||||
2. La sube al registro
|
||||
3. Despliega usando docker-compose
|
||||
|
||||
### Variables Requeridas en Gitea
|
||||
|
||||
Para configurar el despliegue automático, ve a tu repositorio en Gitea:
|
||||
- **Secrets**: `Settings > Actions > Secrets`
|
||||
- **Variables**: `Settings > Actions > Variables`
|
||||
|
||||
**Secrets (valores sensibles):**
|
||||
- `REGISTRY_USERNAME` - Usuario del registro Docker
|
||||
- `REGISTRY_PASSWORD` - Contraseña del registro Docker
|
||||
|
||||
**Variables (valores públicos):**
|
||||
- `REGISTRY_URL` - URL del registro Docker (ej: `gitea.nucleoriofrio.com`)
|
||||
- El owner del repositorio se agrega automáticamente
|
||||
- Imagen final: `REGISTRY_URL/owner/APP_NAME:latest`
|
||||
- `APP_NAME` - Nombre de la aplicación (ej: `mi-app`) - usado para container, imagen y Traefik
|
||||
- `APP_DOMAIN` - Dominio de la aplicación (ej: `miapp.ejemplo.com`)
|
||||
- `NUXT_PUBLIC_APP_URL` - URL pública de la app (ej: `https://miapp.ejemplo.com`)
|
||||
|
||||
📄 Ver ejemplo completo en [`.env.example`](.env.example)
|
||||
|
||||
## Configuración de Traefik y Authentik
|
||||
|
||||
### 🔐 Cómo Funciona Authentik Proxy Outpost
|
||||
|
||||
Authentik Proxy Outpost actúa como un **Forward Auth** middleware que intercepta todas las peticiones antes de que lleguen a tu aplicación:
|
||||
### Arquitectura de Autenticación
|
||||
|
||||
```
|
||||
Usuario → Traefik → Authentik Forward Auth → Aplicación Nuxt
|
||||
↓ (si no auth)
|
||||
Usuario → Traefik → Authentik Forward Auth → App Nuxt
|
||||
↓ (sin sesión)
|
||||
Redirect a Login
|
||||
```
|
||||
|
||||
**Flujo de autenticación:**
|
||||
|
||||
1. **Usuario hace petición** → Traefik recibe la petición a tu dominio
|
||||
2. **Traefik consulta Authentik** → Envía la petición al middleware de Forward Auth
|
||||
3. **Authentik valida sesión:**
|
||||
- ✅ **Con sesión válida**: Authentik agrega headers con info del usuario y envía la petición a tu app
|
||||
- ❌ **Sin sesión**: Authentik redirige al usuario al flujo de login
|
||||
4. **Tu app recibe la petición** → Con headers de usuario ya inyectados (SSR)
|
||||
|
||||
**Ventajas:**
|
||||
- ✅ No necesitas implementar OAuth en tu app
|
||||
- ✅ La autenticación se maneja completamente fuera de tu código
|
||||
- ✅ Los headers llegan automáticamente en cada petición SSR
|
||||
- ✅ Funciona con cualquier framework (Nuxt, Next.js, PHP, etc.)
|
||||
|
||||
### 🚦 Configuración de Reglas de Traefik
|
||||
|
||||
El `docker-compose.yml` configura **dos routers** en Traefik para balancear seguridad y funcionalidad PWA:
|
||||
|
||||
#### Router 1: Rutas Públicas (Sin Autenticación) - Prioridad 100
|
||||
|
||||
```yaml
|
||||
# Rutas que NO requieren autenticación
|
||||
- PathPrefix(`/manifest.webmanifest`) # Manifest PWA
|
||||
- PathPrefix(`/sw.js`) # Service Worker
|
||||
- PathPrefix(`/workbox-`) # Workbox (PWA)
|
||||
- PathPrefix(`/icon-`) # Iconos de la app
|
||||
- PathPrefix(`/apple-touch-icon`) # Icono iOS
|
||||
- PathPrefix(`/favicon.ico`) # Favicon
|
||||
- PathPrefix(`/robots.txt`) # SEO
|
||||
- PathPrefix(`/offline.html`) # Página offline PWA
|
||||
- PathPrefix(`/api/_nuxt_icon/`) # API de iconos de Nuxt
|
||||
```
|
||||
|
||||
**Middlewares aplicados:**
|
||||
- `${APP_NAME}-headers`: Headers personalizados (X-Forwarded-Proto)
|
||||
- `${APP_NAME}-cors`: Configuración CORS para recursos públicos
|
||||
|
||||
**¿Por qué sin autenticación?**
|
||||
- Los Service Workers necesitan acceso sin auth para funcionar offline
|
||||
- Los manifests PWA deben ser públicos para instalación
|
||||
- Prioridad 100 asegura que estas rutas se evalúen primero
|
||||
|
||||
#### Router 2: Aplicación Protegida (Con Autenticación) - Prioridad 10
|
||||
|
||||
```yaml
|
||||
# Todas las demás rutas (Host match)
|
||||
Host(`${APP_DOMAIN}`)
|
||||
```
|
||||
|
||||
**Middlewares aplicados:**
|
||||
- `authentik-forward-auth@file`: Forward Auth de Authentik
|
||||
- `${APP_NAME}-headers`: Headers personalizados
|
||||
|
||||
**Características:**
|
||||
- Prioridad menor (10) → se evalúa después de las rutas públicas
|
||||
- Cualquier ruta no pública pasa por autenticación
|
||||
- Authentik inyecta headers con información del usuario
|
||||
|
||||
### 📋 Configuración de Authentik Proxy Outpost
|
||||
|
||||
**Requisitos previos:**
|
||||
- Traefik corriendo con las redes `traefik-network` y `principal`
|
||||
- Authentik instalado y funcionando
|
||||
|
||||
**Pasos de configuración:**
|
||||
|
||||
#### 1. Crear el Middleware en Traefik
|
||||
|
||||
Crea o edita el archivo de configuración dinámica de Traefik (ej: `dynamic/middlewares.yml`):
|
||||
### Configuración de Middleware (Traefik)
|
||||
|
||||
```yaml
|
||||
# dynamic/middlewares.yml
|
||||
http:
|
||||
middlewares:
|
||||
authentik-forward-auth:
|
||||
@@ -250,84 +340,30 @@ http:
|
||||
- X-authentik-uid
|
||||
```
|
||||
|
||||
**Importante:** Cambia `authentik-server` por el nombre de tu contenedor/servicio de Authentik.
|
||||
### Configuración de Proxy Provider (Authentik)
|
||||
|
||||
#### 2. Configurar Authentik
|
||||
1. **Crear Proxy Provider**:
|
||||
- Type: `Forward auth (single application)`
|
||||
- External host: `https://lotes.nucleoriofrio.com`
|
||||
|
||||
**a) Crear un Proxy Provider:**
|
||||
- Ve a **Admin > Applications > Providers**
|
||||
- Click en **Create**
|
||||
- Tipo: **Proxy Provider**
|
||||
- Configuración:
|
||||
- **Name**: `Mi App - Forward Auth`
|
||||
- **Authorization flow**: Selecciona tu flujo (ej: `default-provider-authorization-implicit-consent`)
|
||||
- **Type**: `Forward auth (single application)`
|
||||
- **External host**: `https://miapp.ejemplo.com` (tu dominio)
|
||||
2. **Crear Application**:
|
||||
- Name: `Seguidor de Lotes`
|
||||
- Slug: `lotes`
|
||||
- Provider: (el creado arriba)
|
||||
|
||||
**b) Crear una Application:**
|
||||
- Ve a **Admin > Applications > Applications**
|
||||
- Click en **Create**
|
||||
- Configuración:
|
||||
- **Name**: `Mi App`
|
||||
- **Slug**: `mi-app`
|
||||
- **Provider**: Selecciona el provider creado arriba
|
||||
3. **Vincular a Outpost**:
|
||||
- Agregar la aplicación al Outpost existente
|
||||
|
||||
**c) Vincular al Outpost:**
|
||||
- Ve a **Admin > Outposts > Outposts**
|
||||
- Edita tu Outpost (o crea uno nuevo si no existe)
|
||||
- En **Applications**: Agrega la aplicación creada
|
||||
### Headers Disponibles en la App
|
||||
|
||||
#### 3. Configurar las Redes en Docker Compose
|
||||
| Header | Descripción |
|
||||
|--------|-------------|
|
||||
| `X-authentik-username` | Nombre de usuario |
|
||||
| `X-authentik-email` | Email |
|
||||
| `X-authentik-name` | Nombre completo |
|
||||
| `X-authentik-groups` | Grupos (separados por `\|`) |
|
||||
| `X-authentik-uid` | ID único |
|
||||
|
||||
Tu aplicación necesita estar en ambas redes:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
principal: # Red de tu infraestructura
|
||||
external: true
|
||||
traefik-network: # Red donde corre Traefik
|
||||
external: true
|
||||
```
|
||||
|
||||
Asegúrate de que estas redes existan:
|
||||
|
||||
```bash
|
||||
docker network create principal
|
||||
docker network create traefik-network
|
||||
```
|
||||
|
||||
### 🔍 Headers Disponibles en tu Aplicación
|
||||
|
||||
Una vez configurado, Authentik inyecta estos headers en cada petición:
|
||||
|
||||
| Header | Descripción | Ejemplo |
|
||||
|--------|-------------|---------|
|
||||
| `X-authentik-username` | Nombre de usuario | `nucleo000` |
|
||||
| `X-authentik-email` | Email del usuario | `user@example.com` |
|
||||
| `X-authentik-name` | Nombre completo | `John Doe` |
|
||||
| `X-authentik-groups` | Grupos (separados por `\|`) | `admins\|users` |
|
||||
| `X-authentik-uid` | ID único del usuario | `703cae063c59...` |
|
||||
|
||||
**En Nuxt**, estos headers se leen automáticamente en SSR mediante `useRequestHeaders()`.
|
||||
|
||||
### 🐛 Troubleshooting
|
||||
|
||||
**Problema: "Cannot find name 'process'"**
|
||||
- ✅ Usa `import.meta.server` en lugar de `process.server` (Nuxt 4)
|
||||
|
||||
**Problema: Redirect loop infinito**
|
||||
- Verifica que el middleware `authentik-forward-auth@file` esté correctamente configurado
|
||||
- Revisa que la aplicación esté asociada al Outpost en Authentik
|
||||
- Comprueba que el External host coincida con tu dominio
|
||||
|
||||
**Problema: Headers no llegan a la aplicación**
|
||||
- Verifica que `authResponseHeaders` incluya todos los headers necesarios
|
||||
- Asegúrate de que estés leyendo headers en SSR (`import.meta.server`)
|
||||
|
||||
**Problema: PWA no funciona offline**
|
||||
- Verifica que las rutas públicas tengan prioridad 100
|
||||
- Confirma que `/sw.js`, `/manifest.webmanifest` y `/offline.html` estén en el router público
|
||||
|
||||
## Licencia
|
||||
## 📄 Licencia
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user