Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/alfonsoolavarria/florilegio/llms.txt

Use this file to discover all available pages before exploring further.

Florilegio cuenta con un sistema completo de cuentas de usuario que combina autenticación propia por correo electrónico con inicio de sesión social vía Google. El registro incluye verificación por correo electrónico con código de 6 dígitos enviado a través de Brevo (ex Sendinblue). Una vez registrados, los usuarios tienen acceso a un perfil personalizable con avatar, a sus estudios bíblicos guardados y, opcionalmente, a planes de suscripción de pago que amplían los límites de uso. Los perfiles de autor están también vinculados al sistema de usuarios, habilitando el portal editorial.

Flujo de registro

1

POST /registro/ — Envío del formulario

El usuario envía su nombre, correo electrónico y contraseña. El sistema valida que el correo no esté en uso y que las contraseñas coincidan.
# El usuario se crea inactivo
user = User.objects.create_user(username=username, email=email, password=password1)
user.is_active = False
user.save()

# Se genera un código de 6 dígitos y se almacena en la sesión
code = str(random.randint(100000, 999999))
request.session['pending_code'] = code
El código se envía al correo del usuario mediante la API de Brevo usando el BREVO_TEMPLATE_ID configurado. Si el envío falla, el usuario creado se elimina y se muestra un error.Límite de tasa: 5 registros por hora por IP.
2

POST /verificar-email/ — Verificación del código

El usuario introduce el código de 6 dígitos recibido por correo. Si coincide con el almacenado en la sesión, la cuenta se activa:
user.is_active = True
user.save()
login(request, user)
El usuario queda autenticado y es redirigido a la URL de origen. Los datos de la sesión temporal se eliminan.
Las variables de entorno BREVO_API_KEY y BREVO_TEMPLATE_ID deben estar configuradas para que el sistema de verificación por correo funcione. Si alguna de ellas está ausente o es inválida, el registro fallará con un mensaje de error explícito y el usuario no será creado. Añádelas a tu archivo .env antes de abrir el registro al público.

Login

Login por correo

POST /iniciar-sesion/ — Autenticación con correo electrónico y contraseña. El backend de Django autentica al usuario por username (que puede ser el correo) o por correo directamente a través del backend personalizado.Límite de tasa: 10 intentos por 15 minutos por IP.

Google OAuth

GET /accounts/ — Inicio de sesión con Google a través de django-allauth. Al autenticarse con Google, si no existe un UserProfile, se crea automáticamente mediante señales de Django.
La integración de Google OAuth con django-allauth requiere configurar SITE_ID en settings.py, añadir allauth, allauth.account y allauth.socialaccount a INSTALLED_APPS, y registrar las credenciales OAuth de Google (SOCIALACCOUNT_PROVIDERS o desde el panel de admin de Sites). Consulta la documentación oficial de django-allauth para los pasos exactos.

Modelo UserProfile

Se crea automáticamente para cada nuevo User mediante señales de Django (post_save). No es necesario crearlo manualmente.
class UserProfile(models.Model):
    PLAN_CHOICES = [
        ('free', 'Gratis'),
        ('premium', 'Premium'),
        ('pro', 'Pro'),
    ]
    user       = models.OneToOneField(User, related_name='profile')
    bio        = models.TextField(blank=True, null=True)
    avatar_url = models.URLField(max_length=500, blank=True, null=True)
    plan       = models.CharField(max_length=20, choices=PLAN_CHOICES, default='free')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def study_limit(self):
        limits = {'free': 3, 'premium': 100, 'pro': None}
        return limits.get(self.plan, 3)

    @property
    def is_author(self):
        return hasattr(self.user, 'author_profile')
Campo / MétodoDescripción
bioBiografía del usuario (opcional)
avatar_urlURL del avatar elegido
planPlan de suscripción: free, premium o pro
created_atFecha de registro del perfil
updated_atFecha de última actualización
study_limit()Retorna 3 (free), 100 (premium) o None (pro = ilimitado)
is_authorTrue si el usuario tiene un perfil Author vinculado

Planes de suscripción

PlanEstudios guardadosPayPal
Free3
Premium100PAYPAL_PLAN_PREMIUM
ProIlimitadoPAYPAL_PLAN_PRO
Los IDs de plan de PayPal se configuran como variables de entorno (PAYPAL_PLAN_PREMIUM, PAYPAL_PLAN_PRO) y se pasan al template de la página /planes/ junto con el PAYPAL_CLIENT_ID.

Activación de suscripción

Una vez que el usuario completa el pago en el frontend de PayPal, el cliente llama a este endpoint para actualizar su plan:
POST /api/paypal/subscription/activate/
Cuerpo de la solicitud:
{
  "subscription_id": "I-BW452GLLEP1G",
  "plan": "premium"
}
Respuesta exitosa:
{
  "status": "success",
  "plan": "premium",
  "subscription_id": "I-BW452GLLEP1G"
}
El endpoint requiere autenticación. El plan debe ser "premium" o "pro". Límite de tasa: 10 solicitudes por hora por usuario/IP.

Avatar

Los usuarios pueden elegir entre un conjunto de avatares pre-cargados en la carpeta static/avatares/. El avatar activo se almacena en UserProfile.avatar_url.
POST /api/perfil/avatar/
Cuerpo de la solicitud:
{
  "avatar": "avatar-01.webp"
}
Respuesta:
{
  "status": "success",
  "avatar": "avatar-01.webp"
}
Los formatos soportados son: .webp, .png, .jpg, .jpeg, .gif.

Modelo UserStudy

Almacena las notas de estudio bíblico guardadas por cada usuario autenticado. El contenido HTML es sanitizado con bleach antes de guardarse.
class UserStudy(models.Model):
    user      = models.ForeignKey(User, related_name='studies')
    title     = models.CharField(max_length=255, blank=True, default='')
    reference = models.CharField(max_length=255, blank=True, default='')
    content   = models.TextField()   # HTML sanitizado con bleach
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-updated_at']
CampoDescripción
titleTítulo libre para la nota de estudio
referenceReferencia bíblica (ej. "Juan 3:16")
contentContenido en HTML, sanitizado con la whitelist de bleach
created_atFecha de creación
updated_atFecha de última modificación; usado para ordenación (-updated_at)

URLs de perfil y estudios

Requiere autenticación. Muestra el perfil del usuario con su plan actual, avatar y datos personales. El template recibe también la lista de archivos de avatar disponibles desde static/avatares/.
GET /perfil/
Requiere autenticación. Lista todos los UserStudy del usuario autenticado, ordenados por updated_at descendente.
GET /mis-estudios/
Crea un nuevo UserStudy o actualiza uno existente si se proporciona study_id. Verifica el límite de estudios del plan antes de crear.
{
  "title": "Análisis de Juan 1:1",
  "reference": "Juan 1:1",
  "content": "<p>En el principio era el Verbo...</p>",
  "study_id": null
}
Límite de tasa: 60 solicitudes por hora por usuario/IP.
Devuelve los datos de un estudio específico del usuario autenticado.
GET /api/estudios/42/
Límite de tasa: 60 solicitudes por hora por usuario/IP.Respuesta:
{
  "status": "success",
  "study": {
    "id": 42,
    "title": "Análisis de Juan 1:1",
    "reference": "Juan 1:1",
    "content": "<p>En el principio era el Verbo...</p>",
    "updated_at": "2025-06-15T10:30:00Z"
  }
}

Build docs developers (and LLMs) love