feat: invitar a un proyecto por correo a alguien que aun no es usuario
Al agregar un miembro, el popup ahora permite elegir un usuario existente o escribir un correo nuevo. Si ese correo no pertenece a nadie, se crea una cuenta en estado 'invited' (nombre/clave placeholder) y se le manda un correo con un enlace de un solo uso para que complete su registro (elige su nombre y clave). La fila de project_members se crea de una vez al invitar, asi que en cuanto acepta ya es miembro sin pasos adicionales. A diferencia del autorregistro publico, no pasa por aprobacion de un admin -- quien lo agrego a su proyecto ya lo vetó. Nuevos endpoints publicos GET /api/auth/invite y POST /api/auth/accept-invite. Nueva pagina AcceptInvitePage (/aceptar-invitacion). Migracion 004 agrega el status 'invited' al enum de users. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+9
-2
@@ -59,10 +59,17 @@
|
||||
editables directo por el cliente: actividad con subtareas = % de subtareas hechas; actividad sin
|
||||
subtareas = manual (0-100); proyecto = promedio del avance de sus actividades.
|
||||
- `users.password_hash` con bcrypt, nunca texto plano ni reversible.
|
||||
- `users.status` (`pending_verification`/`pending_approval`/`active`) es el ciclo de vida del
|
||||
autorregistro, independiente de `is_active` (que sigue siendo el interruptor manual del admin
|
||||
- `users.status` (`pending_verification`/`pending_approval`/`active`/`invited`) es el ciclo de vida
|
||||
de la cuenta, independiente de `is_active` (que sigue siendo el interruptor manual del admin
|
||||
para desactivar a alguien ya activo). Un usuario `pending_approval` rechazado se **borra**
|
||||
físicamente (no hay estado "rechazado" — se audita el email en `audit_log` antes de borrar).
|
||||
- `invited`: cuenta placeholder creada al agregar por correo a alguien que aún no es usuario desde
|
||||
Miembros de un proyecto (`name`=`email`, `password_hash` aleatorio inservible, reutiliza
|
||||
`verification_token`/`verification_token_expires` — 7 días en vez de 24h). Al aceptar la
|
||||
invitación (`POST /api/auth/accept-invite`) pasa directo a `active` **sin pasar por
|
||||
`pending_approval`** — a diferencia del autorregistro público, aquí quien lo invitó ya lo vetó al
|
||||
agregarlo a su proyecto. La fila de `project_members` se crea en el momento de invitar, no al
|
||||
aceptar, así que en cuanto acepta ya aparece como miembro sin pasos adicionales.
|
||||
- `system_settings.value` para `smtp_pass_enc` va **cifrado** (AES-256-GCM, `ENCRYPTION_KEY` del
|
||||
`.env`) — nunca en texto plano, nunca se devuelve por la API (solo `configured: true/false`).
|
||||
- Borrado lógico donde aplique (`users.is_active`); nunca DELETE físico de usuarios **activos** con
|
||||
|
||||
Reference in New Issue
Block a user