Files
Base-QR-Spring-Boot/README.md
Alejandro Lara 59bd2d2d8a Integrar autenticación Cognito con Floci local y soporte AWS
- Añade servicios y configuración Cognito para login web (admins) y API (scanners)
- Soporta Floci cuando AWS_ENDPOINT_URL está definido; AWS real en caso contrario
- Incluye bootstrap Floci, docker-compose.local.yml y carga automática en run-local.sh
- Documenta arquitectura, flujos y arranque manual/IntelliJ en README
- Actualiza gitignore: excluye Flutter, H2 local y artefactos generados
2026-06-09 16:59:50 -06:00

728 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Base Admin Web
Proyecto base de Spring Boot con Metronic, autenticación Cognito (o local), panel administrativo y API de escaneo para la app móvil Flutter.
Sirve como plantilla reutilizable para nuevos paneles internos: estructura modular, seguridad dual (web + API), módulo de códigos pase con QR y soporte H2/PostgreSQL.
---
## Tabla de contenidos
- [Vista general](#vista-general)
- [Stack](#stack)
- [Arquitectura del sistema](#arquitectura-del-sistema)
- [Módulos Maven](#módulos-maven)
- [Seguridad y autenticación](#seguridad-y-autenticación)
- [Cognito: local (Floci) vs AWS](#cognito-local-floci-vs-aws)
- [Módulo de códigos pase](#módulo-de-códigos-pase)
- [API REST](#api-rest)
- [App Flutter (escáner)](#app-flutter-escáner)
- [Arranque local](#arranque-local)
- [Arranque manual e IntelliJ IDEA](#arranque-manual-e-intellij-idea)
- [Perfiles Spring](#perfiles-spring)
- [Variables de entorno](#variables-de-entorno)
- [Objetivo de esta base](#objetivo-de-esta-base)
---
## Vista general
El sistema tiene **dos canales de acceso** con roles distintos:
| Canal | Usuario | Rol | Autenticación |
|-------|---------|-----|---------------|
| Panel web (Thymeleaf) | `admin` | `ROLE_ADMIN` | Sesión HTTP (form login) |
| API móvil / externa | `scanner` | `ROLE_SCANNER` | JWT Bearer (stateless) |
Por defecto ambos canales usan **Amazon Cognito** (emulado en local con Floci). Con `APP_COGNITO_ENABLED=false` se usa autenticación local contra la base de datos y JWT firmado con secreto propio.
```mermaid
flowchart TB
subgraph clients["Clientes"]
Browser["Navegador<br/>Panel admin"]
Flutter["App Flutter<br/>QR Scanner"]
end
subgraph app["Spring Boot — base-admin-web-jar"]
WebChain["Filter chain web<br/>sesión + CSRF"]
ApiChain["Filter chain API<br/>stateless + JWT"]
PassCodes["PassCodeService"]
DB[("H2 / PostgreSQL")]
end
subgraph auth["Autenticación"]
Cognito["Cognito<br/>Floci local o AWS"]
LocalAuth["BD local + JWT HS256<br/>APP_COGNITO_ENABLED=false"]
end
Browser -->|"/login, /admin/**"| WebChain
Flutter -->|"/api/auth/login<br/>/api/pass-codes/scan"| ApiChain
WebChain --> PassCodes
ApiChain --> PassCodes
PassCodes --> DB
WebChain --> Cognito
ApiChain --> Cognito
WebChain -.-> LocalAuth
ApiChain -.-> LocalAuth
```
**URLs locales:**
| Recurso | URL |
|---------|-----|
| Login | http://localhost:8080/login |
| Dashboard | http://localhost:8080/dashboard |
| Códigos pase | http://localhost:8080/admin/pass-codes |
| H2 Console | http://localhost:8080/h2-console |
| Floci (Cognito local) | http://localhost:4566 |
---
## Stack
| Capa | Tecnología |
|------|------------|
| Backend | Spring Boot 4.0.6, Java 25 |
| Seguridad | Spring Security, OAuth2 Resource Server, AWS SDK Cognito |
| Vistas | Thymeleaf + Metronic (`base-web`) |
| Persistencia | JPA / Hibernate, H2 (dev), PostgreSQL (perfil `postgres`) |
| Auth | Cognito (default) o BD local + JWT HS256 |
| Móvil | Flutter (`flutter-app/qrscanner`) |
| Local AWS | [Floci](https://floci.io/floci/getting-started/quick-start/) (Cognito en puerto 4566) |
---
## Arquitectura del sistema
### Capas y dependencias
```mermaid
flowchart BT
jar["base-admin-web-jar<br/>punto de entrada + application.yml"]
web["base-admin-web-web<br/>controladores + Thymeleaf"]
config["base-admin-web-configuration<br/>seguridad, JWT, Cognito"]
app["base-admin-web-application<br/>servicios + carga inicial"]
domain["base-admin-web-domain<br/>entidades + repositorios"]
jar --> web
jar --> config
jar --> app
jar --> domain
web --> config
web --> app
config --> app
app --> domain
```
| Módulo | Responsabilidad |
|--------|-----------------|
| `base-admin-web-domain` | Entidades JPA (`AppUser`, `PassCode`, `Role`), repositorios |
| `base-admin-web-application` | `PassCodeService`, `AppUserDetailsService`, `InitialDataLoader` |
| `base-admin-web-configuration` | `SecurityConfig`, `ApiSecurityConfig`, Cognito, `JwtConfig` |
| `base-admin-web-web` | Controladores MVC y API, DTOs, plantillas HTML |
| `base-admin-web-jar` | `BaseAdminWebApplication`, perfiles, dependencias runtime (H2, PostgreSQL) |
### Dos cadenas de seguridad
Spring Security define **dos filter chains** con distinto comportamiento:
```mermaid
flowchart LR
subgraph order1["@Order(1) — ApiSecurityConfig"]
A1["/api/**"]
A2["Stateless"]
A3["JWT Bearer"]
A4["ROLE_SCANNER en /scan"]
end
subgraph order2["@Order(2) — SecurityConfig"]
B1["Todo excepto /api/**"]
B2["Sesión HTTP"]
B3["Form login /login"]
B4["ROLE_ADMIN en /admin/**"]
end
A1 --> A2 --> A3 --> A4
B1 --> B2 --> B3 --> B4
```
| Ruta | Acceso | Mecanismo |
|------|--------|-----------|
| `/login`, `/assets/**`, `/error`, `/h2-console/**` | Público | — |
| `/dashboard`, `/admin/**` | `ROLE_ADMIN` | Sesión web |
| `/api/auth/login`, `/api/auth/refresh` | Público | Emite tokens (solo `scanner`) |
| `/api/pass-codes/scan` | `ROLE_SCANNER` | JWT Bearer |
---
## Seguridad y autenticación
### Usuarios iniciales
#### Administrador (panel web)
- Usuario: `admin` / `Admin123*`
- Grupo Cognito: `admins``ROLE_ADMIN`
- Acceso: login en `/login`, dashboard, módulo de códigos pase
- El usuario `scanner` **no** puede entrar al panel web
#### Escáner (API / Flutter)
- Usuario: `scanner` / `Scanner123*`
- Grupo Cognito: `scanners``ROLE_SCANNER`
- Acceso: `POST /api/auth/login` y `POST /api/pass-codes/scan`
- El usuario `admin` **no** puede autenticarse por API
### Flujo de login web (panel admin)
```mermaid
sequenceDiagram
actor Admin as Navegador (admin)
participant SC as SecurityConfig
participant CP as CognitoWebAuthenticationProvider
participant CA as CognitoUserAuthenticator
participant Cognito as Cognito (Floci/AWS)
Admin->>SC: POST /login (user, password)
SC->>CP: authenticate()
CP->>CA: admin client + ROLE_ADMIN
CA->>Cognito: InitiateAuth USER_PASSWORD_AUTH
Cognito-->>CA: tokens + cognito:groups
CA-->>CP: AuthenticatedWebUser (grupo admins)
CP-->>SC: sesión HTTP creada
SC-->>Admin: redirect /dashboard
```
**Clases clave:** `SecurityConfig`, `CognitoWebSecurityConfig`, `CognitoWebAuthenticationProvider`, `CognitoUserAuthenticator`, `AuthController`
Con `APP_COGNITO_ENABLED=false`, el flujo usa `DaoAuthenticationProvider``AppUserDetailsService` → tabla `users` (BCrypt).
### Flujo de login y escaneo API
```mermaid
sequenceDiagram
actor App as Flutter (scanner)
participant API as AuthApiController
participant AS as ApiAuthService
participant Cognito as Cognito
participant Scan as PassCodeApiController
participant Svc as PassCodeService
App->>API: POST /api/auth/login
API->>AS: login()
AS->>Cognito: scanner client + ROLE_SCANNER
Cognito-->>App: accessToken, refreshToken, idToken
App->>Scan: POST /api/pass-codes/scan<br/>Authorization: Bearer ...
Scan->>Scan: validar JWT (JWK o HS256)
Scan->>Svc: scan(code)
Svc-->>App: código marcado UTILIZADO
```
**Clases clave:** `ApiSecurityConfig`, `AuthApiController`, `ApiAuthService`, `CognitoAuthService`, `PassCodeApiController`, `JwtConfig`
### Modo local sin Cognito
Con `APP_COGNITO_ENABLED=false` (perfil `test` lo usa automáticamente):
```mermaid
flowchart LR
subgraph web["Web"]
W1["Form login"] --> W2["AppUser en BD"]
end
subgraph api["API"]
A1["POST /api/auth/login"] --> A2["BD + JwtEncoder HS256"]
A3["POST /api/auth/refresh"] --> A4["No disponible"]
A5["Bearer token"] --> A6["localJwtDecoder HS256"]
end
```
| `APP_COGNITO_ENABLED` | Web | API login | Validación JWT | Refresh |
|----------------------|-----|-----------|----------------|---------|
| `true` (default) | Cognito client admin | Cognito client scanner | JWK Set URI | Sí |
| `false` | BD + BCrypt | BD + JWT local | Secreto HS256 | No |
Los usuarios se siembran con `InitialDataLoader` usando `APP_ADMIN_*` y `APP_SCANNER_*`.
---
## Cognito: local (Floci) vs AWS
El SDK de Cognito elige el destino según `AWS_ENDPOINT_URL`:
```mermaid
flowchart TD
Start["APP_COGNITO_ENABLED=true"]
Check{"¿AWS_ENDPOINT_URL<br/>definido?"}
Floci["Floci localhost:4566<br/>credenciales test/test"]
AWS["Cognito real en AWS<br/>DefaultCredentialsProvider<br/>IAM / perfil / env AWS"]
Start --> Check
Check -->|Sí| Floci
Check -->|No| AWS
```
### Local con Floci
`./run-local.sh` hace todo el setup:
1. Levanta Floci (y PostgreSQL si el perfil lo incluye)
2. Espera el bootstrap de Cognito (hasta 120 s)
3. Carga `docker/floci/generated/cognito.local.env` automáticamente
El script `docker/floci/init/ready.d/10-cognito-bootstrap.sh` crea:
| Recurso | Valor |
|---------|-------|
| User Pool ID | `us-east-1_BaseAdminWeb` |
| Usuario admin | `admin` / `Admin123*` → grupo `admins` |
| Usuario scanner | `scanner` / `Scanner123*` → grupo `scanners` |
| App client admin | `base-admin-web-admin` |
| App client scanner | `base-admin-web-scanner` |
Variables generadas en `docker/floci/generated/cognito.local.env` (gitignored).
**Levantar solo Floci:**
```bash
./scripts/floci-up.sh
```
**Levantar stack Docker completo:**
```bash
docker compose -f docker-compose.local.yml up -d
```
| Servicio | Puerto | Persistencia |
|----------|--------|--------------|
| Floci | 4566 | volumen `base_admin_web_floci_data` |
| PostgreSQL | 5432 | volumen `base_admin_web_postgres_data` |
### Producción con AWS Cognito
**No definir** `AWS_ENDPOINT_URL`. Configura el User Pool real:
```bash
export APP_COGNITO_ENABLED=true
export COGNITO_REGION=us-east-1
export COGNITO_USER_POOL_ID=us-east-1_XXXXX
export COGNITO_ISSUER_URI=https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXX
export COGNITO_JWK_SET_URI=https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXX/.well-known/jwks.json
export COGNITO_ADMIN_CLIENT_ID=...
export COGNITO_SCANNER_CLIENT_ID=...
# Credenciales AWS vía IAM role, perfil o AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
```
En AWS replica la misma estructura que Floci: grupos `admins`/`scanners`, clients con `USER_PASSWORD_AUTH` habilitado.
### Verificar Cognito local
```bash
export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
aws cognito-idp list-user-pools --max-results 10 --endpoint-url $AWS_ENDPOINT_URL
aws cognito-idp list-users --user-pool-id us-east-1_BaseAdminWeb --endpoint-url $AWS_ENDPOINT_URL
```
---
## Módulo de códigos pase
Panel para dar de alta y consultar códigos pase con QR.
```mermaid
stateDiagram-v2
[*] --> ACTIVO: admin crea código (10 chars)
ACTIVO --> UTILIZADO: scanner escanea QR
```
| Campo | Descripción |
|-------|-------------|
| Nombre | Etiqueta descriptiva |
| Código | Aleatorio de 10 caracteres (único) |
| Estatus | `ACTIVO` / `UTILIZADO` |
| Escaneado | Indicador booleano |
| Fechas | Creación y escaneo |
**Panel web:** `GET /admin/pass-codes` — tabla Metronic, modal QR, refresco automático al cerrar el modal.
**Entidad:** `PassCode`**Servicio:** `PassCodeService`**Controladores:** `PassCodeController` (web), `PassCodeApiController` (API).
---
## API REST
### Login escáner
```http
POST /api/auth/login
Content-Type: application/json
{
"username": "scanner",
"password": "Scanner123*"
}
```
Respuesta (Cognito):
```json
{
"success": true,
"accessToken": "eyJhbG...",
"refreshToken": "dXMtZWFzdC0x...",
"idToken": "eyJhbG...",
"tokenType": "Bearer",
"expiresIn": 3600,
"username": "scanner",
"roles": ["ROLE_SCANNER"]
}
```
### Renovar token
```http
POST /api/auth/refresh
Content-Type: application/json
{
"refreshToken": "dXMtZWFzdC0x..."
}
```
Solo disponible con Cognito habilitado.
### Escanear código pase
```http
POST /api/pass-codes/scan
Authorization: Bearer eyJhbG...
Content-Type: application/json
{
"code": "K7P2M9XQ4R"
}
```
### Listado JSON (panel admin, requiere sesión)
```http
GET /admin/pass-codes/list
```
---
## App Flutter (escáner)
Ubicación: `flutter-app/qrscanner/`
```mermaid
flowchart LR
Login["LoginScreen"] --> Home["HomeScreen"]
Home --> Scanner["ScannerScreen"]
Scanner -->|QR detectado| API["POST /api/pass-codes/scan"]
Login -->|credenciales| Auth["POST /api/auth/login"]
```
| Archivo | Rol |
|---------|-----|
| `lib/screens/login_screen.dart` | Login y sesión |
| `lib/screens/scanner_screen.dart` | Lectura QR + escaneo |
| `lib/services/auth_service.dart` | Login, SharedPreferences |
| `lib/services/pass_code_service.dart` | Scan con Bearer token |
| `lib/config/api_config.dart` | URL base de la API |
**Ejecutar apuntando al backend local:**
```bash
cd flutter-app/qrscanner
flutter run --dart-define=API_BASE_URL=http://TU_IP:8080
```
La app valida que el usuario tenga `ROLE_SCANNER` (o grupo `scanners`) antes de permitir el escaneo.
---
## Arranque local
### Opción recomendada
```bash
./run-local.sh
```
El script:
- Detecta Java 25 (Temurin)
- Levanta Floci (y PostgreSQL si aplica)
- Espera y carga `cognito.local.env`
- Compila e inicia `base-admin-web-jar`
Si ya tienes `AWS_ENDPOINT_URL` exportado, no sobrescribe tus variables (útil para probar contra AWS).
### Maven manual (terminal)
```bash
# 1. Levantar Floci (Cognito local)
docker compose -f docker-compose.local.yml up -d floci
# 2. Esperar el bootstrap (genera cognito.local.env)
# Revisa que exista: docker/floci/generated/cognito.local.env
# 3. Cargar variables Cognito en la shell
set -a && source docker/floci/generated/cognito.local.env && set +a
# 4. Compilar y arrancar
mvn -pl base-admin-web-jar -am -DskipTests install
mvn -pl base-admin-web-jar spring-boot:run
```
Si Floci ya estaba levantado de antes, basta con el `source` y el `spring-boot:run`.
### PostgreSQL local
```bash
SPRING_PROFILES_ACTIVE=postgres ./run-local.sh
```
### PostgreSQL remoto
```bash
SPRING_PROFILES_ACTIVE=postgres \
SPRING_DATASOURCE_URL=jdbc:postgresql://TU_SERVIDOR:5432/base_admin_web \
SPRING_DATASOURCE_USERNAME=tu_usuario \
SPRING_DATASOURCE_PASSWORD=tu_password \
./run-local.sh
```
---
## Arranque manual e IntelliJ IDEA
Si abres el proyecto en IntelliJ (o cualquier IDE) sin usar `run-local.sh`, debes levantar Floci y configurar variables de entorno tú mismo. `run-local.sh` automatiza exactamente esos pasos.
```mermaid
flowchart TD
A["Abrir proyecto Maven en IntelliJ"] --> B["Java 25 como Project SDK"]
B --> C["docker compose up floci"]
C --> D["Esperar cognito.local.env"]
D --> E["Configurar Run Configuration"]
E --> F["Run BaseAdminWebApplication"]
F --> G["http://localhost:8080/login"]
```
### Requisitos previos
| Requisito | Versión / nota |
|-----------|----------------|
| JDK | **Java 25** (Temurin recomendado) |
| Maven | Incluido en el proyecto (wrapper no obligatorio; usa el Maven del IDE) |
| Docker | Para Cognito local (Floci) en puerto `4566` |
| IntelliJ | Ultimate o Community (con plugin Spring Boot en Community) |
### 1. Importar el proyecto
1. **File → Open** y selecciona la carpeta raíz del repo (donde está el `pom.xml` padre).
2. IntelliJ detecta el proyecto **Maven multi-módulo**. Espera a que termine la indexación e importación.
3. **File → Project Structure → Project**: SDK = **Java 25**, language level = **25**.
4. **File → Settings → Build → Build Tools → Maven → Runner**: JRE = **Project SDK (Java 25)**.
### 2. Levantar Floci (Cognito local)
En una terminal (puede ser la Terminal integrada de IntelliJ):
```bash
docker compose -f docker-compose.local.yml up -d floci
```
La primera vez Floci ejecuta el bootstrap y escribe:
```
docker/floci/generated/cognito.local.env
```
Comprueba que el archivo existe (puede tardar ~30120 s):
```bash
cat docker/floci/generated/cognito.local.env
```
Si no aparece, revisa los logs:
```bash
docker logs base-admin-web-floci
```
**PostgreSQL local:** si usas el perfil `postgres`, levanta también el servicio:
```bash
docker compose -f docker-compose.local.yml up -d postgres floci
```
### 3. Run Configuration en IntelliJ
Crea una configuración **Spring Boot** (o **Application**):
| Campo | Valor |
|-------|-------|
| **Name** | `BaseAdminWebApplication` |
| **Main class** | `mx.gob.slp.baseadminweb.jar.BaseAdminWebApplication` |
| **Module** | `base-admin-web-jar` |
| **Working directory** | `$PROJECT_DIR$/base-admin-web-jar` |
| **Active profiles** | `dev` (o `postgres` si aplica) |
> **Working directory:** H2 guarda datos en `./data/h2/` relativo al directorio de trabajo. Debe ser `base-admin-web-jar` para que coincida con `mvn spring-boot:run` y no mezclar rutas de BD.
#### Variables de entorno (Cognito local)
En **Environment variables**, pega el contenido de `docker/floci/generated/cognito.local.env`:
```
COGNITO_USER_POOL_ID=us-east-1_BaseAdminWeb
COGNITO_REGION=us-east-1
COGNITO_ISSUER_URI=http://localhost:4566/us-east-1_BaseAdminWeb
COGNITO_JWK_SET_URI=http://localhost:4566/us-east-1_BaseAdminWeb/.well-known/jwks.json
COGNITO_ADMIN_CLIENT_ID=<valor del archivo generado>
COGNITO_SCANNER_CLIENT_ID=<valor del archivo generado>
COGNITO_ADMIN_GROUP=admins
COGNITO_SCANNER_GROUP=scanners
AWS_ENDPOINT_URL=http://localhost:4566
AWS_DEFAULT_REGION=us-east-1
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
```
Los `CLIENT_ID` cambian en cada bootstrap; **copia siempre los del archivo generado**, no uses valores fijos de ejemplos antiguos.
**Alternativa:** plugin [EnvFile](https://plugins.jetbrains.com/plugin/7861-envfile) → añade `docker/floci/generated/cognito.local.env` como archivo de entorno en la Run Configuration.
#### Perfil `postgres` en IntelliJ
Además de **Active profiles** = `postgres`, añade en Environment variables:
```
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/base_admin_web
SPRING_DATASOURCE_USERNAME=postgres
SPRING_DATASOURCE_PASSWORD=postgres
```
(Y las variables Cognito del paso anterior.)
### 4. Ejecutar
1. **Build → Build Project** (o `Ctrl+F9`).
2. Run ▶ en `BaseAdminWebApplication`.
3. Abre http://localhost:8080/login — usuario `admin` / `Admin123*`.
### 5. Desarrollo sin Docker (modo local puro)
Si no quieres Floci, desactiva Cognito y usa usuarios de la BD:
| Variable | Valor |
|----------|-------|
| `APP_COGNITO_ENABLED` | `false` |
No hace falta `AWS_ENDPOINT_URL` ni levantar Docker. Los usuarios `admin` y `scanner` se crean al arrancar vía `InitialDataLoader`.
El login API devuelve JWT local (HS256); **refresh no está disponible** en este modo.
### 6. Checklist de problemas frecuentes
| Síntoma | Causa probable | Solución |
|---------|----------------|----------|
| Login web falla con Cognito habilitado | Floci no está arriba o faltan env vars | `docker compose up -d floci` + cargar `cognito.local.env` |
| Login va a AWS real en local | Falta `AWS_ENDPOINT_URL` | Definir `AWS_ENDPOINT_URL=http://localhost:4566` |
| `Invalid client id` | Client IDs desactualizados | Regenerar con bootstrap y copiar de `cognito.local.env` |
| H2 vacío o ruta rara | Working directory incorrecto | `$PROJECT_DIR$/base-admin-web-jar` |
| Error de versión Java | SDK distinto a 25 | Project Structure → SDK Java 25 |
| Tests en IDE fallan por Cognito | Perfil `test` desactiva Cognito | Ejecutar tests con perfil `test` (ya configurado en `application-test.yml`) |
### 7. Comandos útiles desde IntelliJ
| Acción | Comando Maven (ventana Maven o terminal) |
|--------|------------------------------------------|
| Compilar todo | `mvn -pl base-admin-web-jar -am -DskipTests install` |
| Tests | `mvn test` |
| Solo módulo jar | clic derecho en `base-admin-web-jar` → Run Maven → `spring-boot:run` (tras exportar env vars en la shell) |
---
## Perfiles Spring
| Perfil | Base de datos | Cognito | Uso |
|--------|---------------|---------|-----|
| `dev` (default) | H2 en archivo `./data/h2/` | Floci (manual o `run-local.sh`) | Desarrollo diario |
| `postgres` | PostgreSQL | Floci | Desarrollo con BD real |
| `prod` | Configurable | AWS | Producción |
| `test` | H2 en memoria `create-drop` | Deshabilitado | `mvn test` |
---
## Variables de entorno
### Aplicación
| Variable | Default | Descripción |
|----------|---------|-------------|
| `SERVER_PORT` | `8080` | Puerto HTTP |
| `SPRING_PROFILES_ACTIVE` | `dev` | Perfil Spring |
| `APP_TITLE` | `Base Admin Web` | Título en vistas |
### Cognito
| Variable | Local (Floci) | Producción (AWS) |
|----------|---------------|------------------|
| `APP_COGNITO_ENABLED` | `true` | `true` |
| `COGNITO_REGION` | `us-east-1` | tu región |
| `COGNITO_USER_POOL_ID` | `us-east-1_BaseAdminWeb` | `us-east-1_XXXXX` |
| `COGNITO_ISSUER_URI` | `http://localhost:4566/...` | `https://cognito-idp.{region}.amazonaws.com/{poolId}` |
| `COGNITO_JWK_SET_URI` | `http://localhost:4566/.../jwks.json` | `https://cognito-idp.{region}.amazonaws.com/{poolId}/.well-known/jwks.json` |
| `COGNITO_ADMIN_CLIENT_ID` | generado por Floci | client del pool |
| `COGNITO_SCANNER_CLIENT_ID` | generado por Floci | client del pool |
| `COGNITO_ADMIN_GROUP` | `admins` | `admins` |
| `COGNITO_SCANNER_GROUP` | `scanners` | `scanners` |
| `AWS_ENDPOINT_URL` | `http://localhost:4566` | **no definir** |
### Base de datos
| Variable | Descripción |
|----------|-------------|
| `SPRING_DATASOURCE_URL` | JDBC URL |
| `SPRING_DATASOURCE_USERNAME` | Usuario BD |
| `SPRING_DATASOURCE_PASSWORD` | Contraseña BD |
| `SPRING_JPA_HIBERNATE_DDL_AUTO` | `update` por defecto |
### JWT local (solo `APP_COGNITO_ENABLED=false`)
| Variable | Descripción |
|----------|-------------|
| `APP_JWT_SECRET` | Secreto HS256 (mín. 32 caracteres) |
| `APP_JWT_EXPIRATION_HOURS` | Expiración del token |
### Usuarios semilla (modo local sin Cognito)
| Variable | Default |
|----------|---------|
| `APP_ADMIN_USERNAME` / `APP_ADMIN_PASSWORD` | `admin` / `Admin123*` |
| `APP_SCANNER_USERNAME` / `APP_SCANNER_PASSWORD` | `scanner` / `Scanner123*` |
---
## Objetivo de esta base
Esta base deja resuelto lo mínimo para arrancar nuevos proyectos internos:
- Autenticación Cognito (local y AWS) con fallback a BD local
- Panel web con Metronic y sesión HTTP para administradores
- API stateless con JWT para escaneo móvil o externo
- App Flutter de referencia para escaneo QR
- Módulo de códigos pase con alta, listado, QR y API de escaneo
- Estructura modular Maven limpia
- Soporte rápido para H2 y PostgreSQL
- Floci para desarrollo sin depender de AWS
El dashboard se mantiene deliberadamente sencillo como punto de partida para futuras integraciones.