feat: warn user about email change
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
# Crochet
|
||||
|
||||
Aplicación web para diseñar patrones de crochet con un editor visual,
|
||||
exportarlos a PDF y compartirlos con un enlace de solo lectura. Incluye
|
||||
cuentas de usuario para guardar y gestionar los propios patrones.
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
- **Editor visual de patrones**: secciones de título, subtítulo, texto,
|
||||
nota, materiales, imágenes y "patrón" (puntos con contador), todo
|
||||
reordenable por arrastre. El contenido se guarda bilingüe (es/en).
|
||||
- **Personalización de página**: título, autor, imagen de portada, color de
|
||||
texto/acento/fondo, tipografía, tamaño de letra, alineación, tamaño y
|
||||
orientación de página.
|
||||
- **Exportación a PDF** con WeasyPrint, usando el propio diálogo de
|
||||
impresión del navegador.
|
||||
- **Vista de solo lectura compartible** (`pattern/<uuid>/`), sin necesidad
|
||||
de cuenta ni de cargar el editor.
|
||||
- **Cuentas de usuario**: registro (con email, necesario para poder
|
||||
recuperar la contraseña), login/logout, ajustes de cuenta (cambiar
|
||||
email/contraseña, con HTMX) y recuperación de contraseña por email.
|
||||
Cada patrón pertenece a quien lo creó; solo su propietario puede
|
||||
editarlo o borrarlo.
|
||||
- **"Mis patrones"**: listado de los patrones propios con portada, fecha de
|
||||
actualización y accesos directos a editar/ver/eliminar.
|
||||
- **i18n completo** (español/inglés): interfaz, URLs traducidas
|
||||
(`/es/patron/...` frente a `/en/pattern/...`) y contenido del propio
|
||||
patrón.
|
||||
|
||||
## Stack técnico
|
||||
|
||||
- **Backend**: Django 6, servido en ASGI con Uvicorn.
|
||||
- **Base de datos**: PostgreSQL en producción, SQLite por defecto en
|
||||
desarrollo (configurable con `DATABASE_URL`).
|
||||
- **Frontend del editor**: JavaScript vanilla (sin framework ni bundler),
|
||||
daisyUI + Tailwind CSS vía CDN con compilador JIT.
|
||||
- **Vista de solo lectura / PDF**: Tailwind precompilado sin JS (WeasyPrint
|
||||
no ejecuta JavaScript), generado con el CLI standalone de Tailwind (ver
|
||||
`python manage.py build_pattern_detail_css`).
|
||||
- **Imágenes**: Pillow (variantes de la portada del patrón en varios
|
||||
tamaños), almacenamiento en filesystem o S3 (`django-storages`, opcional).
|
||||
- **Estáticos**: WhiteNoise con manifest comprimido.
|
||||
- **HTMX** para los formularios de ajustes de cuenta.
|
||||
- **Gestión de dependencias**: [uv](https://docs.astral.sh/uv/).
|
||||
|
||||
## Desarrollo
|
||||
|
||||
### Requisitos
|
||||
|
||||
- Python 3.13
|
||||
- [uv](https://docs.astral.sh/uv/)
|
||||
- Librerías nativas de WeasyPrint (Pango, Cairo, GDK-Pixbuf) si vas a
|
||||
generar/probar el PDF fuera de Docker — en Debian/Ubuntu:
|
||||
`apt-get install libpango-1.0-0 libpangocairo-1.0-0 fonts-dejavu-core`.
|
||||
- `gettext` si vas a regenerar/compilar traducciones
|
||||
(`msgfmt`/`msguniq`/etc.) — en Debian/Ubuntu: `apt-get install gettext`.
|
||||
|
||||
### Puesta en marcha
|
||||
|
||||
```bash
|
||||
git clone <url-del-repositorio>
|
||||
cd crochet
|
||||
uv sync --group dev
|
||||
```
|
||||
|
||||
Crea un archivo `.env` en la raíz del proyecto (ver
|
||||
[Variables de entorno](#variables-de-entorno) más abajo). Para desarrollo
|
||||
local basta con:
|
||||
|
||||
```env
|
||||
DEBUG=True
|
||||
```
|
||||
|
||||
Con eso, la app arranca con SQLite, `SECRET_KEY` de desarrollo, envío de
|
||||
email al backend de consola (se imprime en la terminal en vez de mandarse
|
||||
de verdad) y sin credenciales adicionales.
|
||||
|
||||
```bash
|
||||
uv run python manage.py migrate
|
||||
uv run python manage.py createsuperuser # opcional, para /admin/
|
||||
uv run python manage.py runserver
|
||||
```
|
||||
|
||||
La app queda disponible en `http://localhost:8000/`.
|
||||
|
||||
### Tests
|
||||
|
||||
```bash
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
`pytest-cov` está incluido; para ver cobertura: `uv run pytest --cov`.
|
||||
|
||||
### Traducciones
|
||||
|
||||
Las cadenas ya traducidas están compiladas y listas para usar. Si añades o
|
||||
cambias texto traducible (`{% trans %}`/`{% blocktrans %}`, `gettext_lazy`):
|
||||
|
||||
```bash
|
||||
uv run python manage.py makemessages -l es -l en
|
||||
# revisa a mano cualquier entrada marcada como "#, fuzzy" antes de compilar
|
||||
uv run python manage.py compilemessages
|
||||
```
|
||||
|
||||
### CSS precompilado de la vista de solo lectura / PDF
|
||||
|
||||
Solo hace falta volver a generarlo si cambian las clases de Tailwind
|
||||
usadas en `pattern_detail.html` o `pattern_render.py`:
|
||||
|
||||
```bash
|
||||
uv run python manage.py build_pattern_detail_css
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker build -t crochet .
|
||||
docker run --rm -p 8000:8000 --env-file .env crochet
|
||||
```
|
||||
|
||||
El `Dockerfile` instala las dependencias del sistema necesarias para
|
||||
WeasyPrint y ejecuta `scripts/build.sh` (CSS precompilado, `collectstatic`,
|
||||
`compilemessages`) al construir la imagen, y `scripts/run.sh` (Uvicorn) al
|
||||
arrancar el contenedor.
|
||||
|
||||
## Variables de entorno
|
||||
|
||||
Todas se leen en `config/settings/env.py`; sin `.env`, o si falta alguna,
|
||||
se usan los valores por defecto indicados (pensados para desarrollo local).
|
||||
|
||||
| Variable | Por defecto | Descripción |
|
||||
|---|---|---|
|
||||
| `SECRET_KEY` | clave insegura de desarrollo | **Cámbiala en producción.** |
|
||||
| `DEBUG` | `False` | Activa páginas de error detalladas, Django Debug Toolbar y Silk. No debe estar activo en producción. |
|
||||
| `ALLOWED_HOSTS` | `*` | Lista separada por comas. Debe restringirse a los dominios reales en producción. |
|
||||
| `CSRF_TRUSTED_ORIGINS` | `http://localhost:8000` | Lista separada por comas. Necesario si la app se sirve detrás de un dominio/HTTPS distinto. |
|
||||
| `DATABASE_URL` | `sqlite:///db.sqlite3` | Formato `django-environ` (p. ej. `postgres://usuario:password@host:5432/nombre_bd`). |
|
||||
| `S3_ENABLED` | `False` | Si es `True`, los archivos subidos (imágenes de portada/patrón) se guardan en S3 en vez de en el filesystem local. |
|
||||
| `S3_ACCESS_KEY_ID` / `S3_SECRET_ACCESS_KEY` / `S3_STORAGE_BUCKET_NAME` / `S3_ENDPOINT_URL` | vacío | Credenciales del bucket, solo necesarias si `S3_ENABLED=True`. |
|
||||
| `EMAIL_BACKEND` | backend de consola | Usa `django.core.mail.backends.smtp.EmailBackend` para enviar emails de verdad (recuperación de contraseña). |
|
||||
| `EMAIL_HOST` / `EMAIL_HOST_USER` / `EMAIL_HOST_PASSWORD` / `EMAIL_PORT` | vacío / vacío / vacío / `587` | Credenciales SMTP, solo con el backend SMTP. |
|
||||
| `DEFAULT_FROM_EMAIL` | `webmaster@localhost` | Remitente de los emails salientes. La mayoría de proveedores SMTP rechazan enviar si no coincide con la cuenta autenticada (o un alias verificado). |
|
||||
| `SUPPORT_EMAIL` | `soporte@localhost` | Dirección de contacto que se muestra en el aviso que recibe el email anterior de una cuenta cuando alguien lo cambia (ver `EmailUpdateForm`). |
|
||||
| `LOG_LEVEL` | `INFO` | Nivel de log de Django y de la app (`crochet`). |
|
||||
|
||||
Existen además `CORS_ORIGIN_WHITELIST`, `REDIS_HOST`, `REDIS_PORT`,
|
||||
`CELERY_BROKER_URL`, `PAGE_SIZE` e `ITEMS_PER_PAGE` en `env.py`: quedaron de
|
||||
una plantilla de proyecto y actualmente no los usa ninguna parte de la
|
||||
aplicación (no hay Celery, cachés en Redis, CORS ni paginación
|
||||
configurados), así que no hace falta definirlos para desplegar.
|
||||
|
||||
## Despliegue a producción
|
||||
|
||||
Como mínimo hay que ajustar, respecto al `.env` de desarrollo:
|
||||
|
||||
1. **`SECRET_KEY`**: un valor único y secreto (no el de desarrollo).
|
||||
2. **`DEBUG=False`**.
|
||||
3. **`ALLOWED_HOSTS`**: los dominios reales, no `*`.
|
||||
4. **`CSRF_TRUSTED_ORIGINS`**: los orígenes reales (con esquema, p. ej.
|
||||
`https://patrones.ejemplo.com`).
|
||||
5. **`DATABASE_URL`**: apuntando a PostgreSQL.
|
||||
6. **`EMAIL_BACKEND`/`EMAIL_HOST`/`EMAIL_HOST_USER`/`EMAIL_HOST_PASSWORD`/`DEFAULT_FROM_EMAIL`**:
|
||||
sin esto, el registro de usuarios funciona pero la recuperación de
|
||||
contraseña no llega a enviarse (se queda en el log en vez de salir por
|
||||
SMTP).
|
||||
7. **Almacenamiento de archivos**: si vas a correr más de una instancia o
|
||||
quieres que las imágenes sobrevivan a un redeploy del contenedor,
|
||||
configura `S3_ENABLED=True` y las credenciales de `S3_*` — el
|
||||
filesystem local (por defecto) no es compartido ni persistente entre
|
||||
despliegues.
|
||||
|
||||
La imagen Docker ya ejecuta `collectstatic`, `compilemessages` y el
|
||||
CSS precompilado al construirse, y sirve la app con Uvicorn (variables
|
||||
`WSGI_HOST`/`WSGI_WORKERS` para ajustar host/nº de workers). WhiteNoise se
|
||||
encarga de servir los estáticos directamente desde la propia app, sin
|
||||
necesidad de un servidor/proxy de estáticos aparte.
|
||||
|
||||
Al hacer push a `master` se dispara la integración continua (tests) y,
|
||||
si pasan, se construye y publica una imagen Docker (ver
|
||||
`.gitea/workflows/test-build.yaml`).
|
||||
|
||||
Reference in New Issue
Block a user