Setup completo del portal interno donna.aal-law.com: * Landing público con OAuth login + grid de apps autenticado * Flujo OAuth2 contra Mailcow (mail.aal-law.com) * Sesiones SSO compartidas en el dominio (cookie donna_session, 8h) * Whitelist de dominios aal-law.com / aalnlaw.com * App "Control de Escrituras" migrada desde ZH-Consultores/control-escrituras (mismo schema, mismo frontend, ahora con shared Auth/Db/Config libs) * Migraciones SQL para users, escrituras_tramites, escrituras_historial * Caddy on :80 con rewrite extless → .php * Backup diario MariaDB (systemd timer + script) con retención 14d * Documentación de arquitectura en README + infra files en docs/infra
207 lines
7.0 KiB
Markdown
207 lines
7.0 KiB
Markdown
# Donna — Portal interno AALN Law
|
|
|
|
Portal interno de la firma **Arias, Abrego, López & Noriega** (aalnlaw.com) que aloja herramientas internas para el equipo. Primer app embarcada: **Control de Escrituras Públicas**.
|
|
|
|
> Producción: <https://donna.aal-law.com>
|
|
|
|
---
|
|
|
|
## Arquitectura
|
|
|
|
```
|
|
Navegador
|
|
│ HTTPS
|
|
▼
|
|
Cloudflare → Caddy infra (SSL termination)
|
|
│ HTTP :80
|
|
▼
|
|
┌──────────────────────┐
|
|
│ Caddy (este server) │ /opt/donna/public
|
|
│ rewrite *.php │
|
|
└──────┬───────────────┘
|
|
│ unix socket
|
|
▼
|
|
┌──────────────────────┐
|
|
│ PHP-FPM 8.4 │
|
|
└──────┬───────────────┘
|
|
▼
|
|
┌──────────────────────┐
|
|
│ MariaDB 11.8 │ DB: donna
|
|
└──────────────────────┘
|
|
```
|
|
|
|
**Stack:**
|
|
- PHP 8.4-fpm (`/run/php/php8.4-fpm.sock`)
|
|
- Caddy 2.6 en `:80`
|
|
- MariaDB 11.8 (`127.0.0.1:3306`)
|
|
- Autenticación OAuth2 contra Mailcow (`mail.aal-law.com`)
|
|
- Backups diarios automáticos vía systemd timer
|
|
|
|
---
|
|
|
|
## Estructura del repo
|
|
|
|
```
|
|
donna/
|
|
├── public/ ← DocumentRoot
|
|
│ ├── index.php ← Landing + grid de apps
|
|
│ ├── auth/
|
|
│ │ ├── login.php ← Inicia OAuth flow
|
|
│ │ ├── callback.php ← Recibe code de Mailcow
|
|
│ │ └── logout.php
|
|
│ └── escrituras/
|
|
│ ├── index.php ← Auth-guard + sirve view
|
|
│ └── api.php ← CRUD trámites + historial
|
|
├── src/ ← Librerías PHP compartidas (fuera de DocumentRoot)
|
|
│ ├── Config.php ← Lee /etc/donna/donna.env
|
|
│ ├── Db.php ← PDO singleton
|
|
│ ├── Auth.php ← Sesión + OAuth guard + whitelist
|
|
│ ├── Oauth.php ← Cliente HTTP a Mailcow
|
|
│ └── Apps.php ← Catálogo de apps del menú
|
|
├── views/ ← Templates HTML servidos por PHP tras auth
|
|
│ └── escrituras.html
|
|
├── sql/ ← Migraciones (aplicar manualmente)
|
|
│ ├── 001_core.sql ← users
|
|
│ └── 002_escrituras.sql ← escrituras_tramites + escrituras_historial
|
|
├── bin/
|
|
│ └── donna-backup.sh ← mysqldump diario, retención 14 días
|
|
├── docs/ ← Diseños y archivos de infra de referencia
|
|
├── donna.env.example ← Plantilla del archivo de secrets
|
|
└── README.md
|
|
```
|
|
|
|
**Fuera del repo (en el servidor):**
|
|
- `/etc/donna/donna.env` — secrets reales (`640 root:www-data`)
|
|
- `/etc/caddy/Caddyfile` — config del Caddy local
|
|
- `/etc/systemd/system/donna-backup.{service,timer}` — backups
|
|
- `/var/log/donna/` — access logs
|
|
- `/var/backups/donna/` — dumps SQL
|
|
|
|
---
|
|
|
|
## Setup en un servidor nuevo
|
|
|
|
```bash
|
|
# 1. Paquetes del SO (Debian 13)
|
|
apt install -y caddy php8.4-fpm php8.4-mysql php8.4-curl \
|
|
php8.4-mbstring php8.4-intl php8.4-zip mariadb-server
|
|
|
|
# 2. Base de datos
|
|
mariadb -e "CREATE DATABASE donna CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
|
mariadb -e "CREATE USER 'donna_app'@'localhost' IDENTIFIED BY 'XXX';
|
|
GRANT ALL ON donna.* TO 'donna_app'@'localhost';"
|
|
|
|
# 3. Código
|
|
git clone https://git.zhconsultores.com/ZH-Consultores/donna.git /opt/donna
|
|
chown -R www-data:www-data /opt/donna
|
|
|
|
# 4. Migraciones
|
|
mariadb donna < /opt/donna/sql/001_core.sql
|
|
mariadb donna < /opt/donna/sql/002_escrituras.sql
|
|
|
|
# 5. Secrets
|
|
mkdir -p /etc/donna
|
|
cp /opt/donna/donna.env.example /etc/donna/donna.env
|
|
# Editar /etc/donna/donna.env con valores reales (OAuth, DB_PASS, APP_SECRET)
|
|
chown root:www-data /etc/donna/donna.env
|
|
chmod 640 /etc/donna/donna.env
|
|
|
|
# 6. Caddy y backups: ver docs/infra/ para Caddyfile y systemd units
|
|
systemctl reload caddy
|
|
systemctl enable --now donna-backup.timer
|
|
```
|
|
|
|
---
|
|
|
|
## OAuth2 con Mailcow
|
|
|
|
1. En `https://mail.aal-law.com/admin` → **Access → OAuth2 Apps**
|
|
2. Crear app con `Redirect URI = https://donna.aal-law.com/auth/callback`
|
|
3. Copiar `Client ID` y `Client Secret` a `/etc/donna/donna.env`
|
|
|
|
El flujo:
|
|
```
|
|
/ ──login──▶ /auth/login.php ──redirect──▶ mail.aal-law.com/oauth/authorize
|
|
│
|
|
▼ ?code=...&state=...
|
|
/auth/callback.php ◀── redirect ◀── usuario autorizado
|
|
│
|
|
├── valida state (anti-CSRF)
|
|
├── intercambia code → token
|
|
├── lee profile (email, nombre)
|
|
├── valida dominio @aal-law.com o @aalnlaw.com
|
|
├── inserta/actualiza fila en `users`
|
|
└── redirige a /
|
|
```
|
|
|
|
Sesión: cookie `donna_session`, `path=/`, `Secure`, `HttpOnly`, `SameSite=Lax`, lifetime 8h. SSO automático entre todas las apps del portal.
|
|
|
|
---
|
|
|
|
## Apps
|
|
|
|
Las apps se registran en `src/Apps.php::catalog()`. El landing las renderiza automáticamente como cards.
|
|
|
|
| Slug | Estado | Ruta | Tablas DB |
|
|
|---|---|---|---|
|
|
| `escrituras` | Live | `/escrituras/` | `escrituras_tramites`, `escrituras_historial` |
|
|
| `casos` | Coming soon | — | — |
|
|
| `agenda` | Coming soon | — | — |
|
|
| `clientes` | Coming soon | — | — |
|
|
|
|
**Para agregar una app nueva:**
|
|
1. Crear `/opt/donna/public/<slug>/index.php` con `Auth::requireAuth()` arriba.
|
|
2. Crear `/opt/donna/public/<slug>/api.php` si necesita backend.
|
|
3. Prefijar todas las tablas DB con `<slug>_`.
|
|
4. Crear migración en `sql/00N_<slug>.sql`.
|
|
5. Registrar en `src/Apps.php::catalog()`.
|
|
6. Commit + push.
|
|
|
|
---
|
|
|
|
## Identidad visual
|
|
|
|
| Token | Valor |
|
|
|---|---|
|
|
| `--navy` | `#1B3A6B` |
|
|
| `--navy-d` | `#112446` |
|
|
| `--navy-l` | `#2D5090` |
|
|
| `--gold` | `#C9A84C` |
|
|
| `--gold-l` | `#E8C96A` |
|
|
| `--gold-d` | `#9E7C2E` |
|
|
| `--off` | `#F7F6F3` |
|
|
| Fuente headlines | DM Serif Display |
|
|
| Fuente UI | DM Sans |
|
|
|
|
Gradient hero del landing: `#0E1F3F → #1B3A6B → #2D5090`.
|
|
|
|
---
|
|
|
|
## Backups
|
|
|
|
`donna-backup.timer` ejecuta diariamente a las 03:00 (con jitter de ±5min) y vuelca `donna` comprimido a `/var/backups/donna/donna-YYYY-MM-DD_HHMMSS.sql.gz`. Retención 14 días.
|
|
|
|
Restaurar:
|
|
```bash
|
|
gunzip -c /var/backups/donna/donna-2026-MM-DD_HHMMSS.sql.gz | mariadb donna
|
|
```
|
|
|
|
---
|
|
|
|
## Operación
|
|
|
|
| Acción | Comando |
|
|
|---|---|
|
|
| Reload Caddy | `systemctl reload caddy` |
|
|
| Reload PHP-FPM | `systemctl reload php8.4-fpm` |
|
|
| Ver logs Caddy | `tail -f /var/log/donna/access.log` |
|
|
| Ver errores PHP | `journalctl -u php8.4-fpm -f` |
|
|
| Backup manual | `/opt/donna/bin/donna-backup.sh` |
|
|
| Próximo backup | `systemctl list-timers donna-backup.timer` |
|
|
|
|
---
|
|
|
|
## Licencia
|
|
|
|
Software interno — sin licencia pública. Propiedad de **Arias, Abrego, López & Noriega**.
|