Files
NightSpire/home/models/accounts.py
T
Inna 585285640d Divide home/models.py en el paquete home/models/ por secciones
El módulo (~310 líneas, 30 modelos) se convierte en un paquete cuyo
__init__.py re-exporta todos los modelos, de modo que `from home.models
import X`, el admin y el resto de consumidores siguen funcionando igual.

Módulos por sección: pricing (precios/costes de servicios + GuildRenameSettings),
store (Category, Item, StripeLog, Pedido), site (contenido/config del sitio),
recruit, accounts (activación, token de seguridad, LoginAttempt), voting
(VoteSite, VoteLog, HomeApiPoints) e history. Las claves foráneas por clase
directa quedan en el mismo módulo; cada submódulo importa solo lo que usa.

Se eliminan imports de cabecera muertos (ValidationError, uuid, secrets) y las
líneas de import duplicadas del original.

Migración-neutral: `makemigrations home --dry-run` -> "No changes detected"
(app_label=home y nombres/tablas de modelo intactos). Definición de cada
modelo idéntica (extracción por AST). `manage.py check` sin incidencias.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:15:12 +00:00

49 lines
2.3 KiB
Python

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class AccountActivation(models.Model):
# En 3.4.3 (Battle.net) la identidad es el email; el username de la cuenta
# de juego se genera al activar (<bnetId>#1), por eso es opcional aquí.
username = models.CharField(max_length=17, null=True, blank=True)
email = models.EmailField()
old_email = models.EmailField(null=True, blank=True)
password = models.CharField(max_length=64)
# salt/verifier ya no se precalculan en el registro (se calculan al activar,
# tanto el de bnet como el de la cuenta de juego). Se conservan opcionales
# por compatibilidad con el flujo de cambio de email.
salt = models.BinaryField(max_length=32, null=True, blank=True)
verifier = models.BinaryField(max_length=256, null=True, blank=True)
recruiter_id = models.IntegerField(null=True, blank=True)
hash = models.CharField(max_length=32, unique=True)
old_email_hash = models.CharField(max_length=32, null=True, blank=True)
is_used = models.BooleanField(default=False) # Indica si el old_email_hash ha sido usado
is_new_email_used = models.BooleanField(default=False) # Indica si el hash del nuevo correo ha sido usado
created_at = models.DateTimeField(default=timezone.now)
def is_expired(self):
return timezone.now() > self.created_at + timezone.timedelta(hours=1)
def __str__(self):
return f"Activation for {self.username}"
class SecurityToken(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
token = models.CharField(max_length=6)
created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField()
ip_address = models.GenericIPAddressField()
def __str__(self):
return f"Token for {self.user.username if self.user else 'Desconocido'}"
class LoginAttempt(models.Model):
username = models.CharField(max_length=100)
status = models.CharField(max_length=50) # Ejemplo: 'Éxito' o 'Fracaso'
ip_address = models.GenericIPAddressField() # IP del intento de inicio de sesión
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.username} - {self.status} - {self.timestamp}"