817 |
817 |
class SMSCode(models.Model):
|
818 |
818 |
CODE_DURATION = 120
|
819 |
819 |
KIND_REGISTRATION = 'registration'
|
820 |
|
KIND_PASSWORD_LOST = 'password-lost'
|
|
820 |
KIND_PASSWORD_LOST = 'pw-reset'
|
821 |
821 |
value = models.CharField(
|
822 |
822 |
verbose_name=_('Identifier'), default=create_sms_code, editable=False, max_length=32
|
823 |
823 |
)
|
... | ... | |
825 |
825 |
phone = models.CharField(
|
826 |
826 |
_('phone number'), null=True, blank=True, max_length=64, validators=[PhoneNumberValidator]
|
827 |
827 |
)
|
|
828 |
user = models.ForeignKey(
|
|
829 |
settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE, null=True
|
|
830 |
)
|
828 |
831 |
url_token = models.UUIDField(
|
829 |
832 |
verbose_name=_('URL token'),
|
830 |
833 |
default=uuid.uuid4,
|
... | ... | |
833 |
836 |
expires = models.DateTimeField(verbose_name=_('Expires'))
|
834 |
837 |
sent = models.BooleanField(default=False, verbose_name=_('SMS code sent'))
|
835 |
838 |
|
|
839 |
# fake codes to avoid disclosing account existence info on unjustified password reset attempts
|
|
840 |
fake = models.BooleanField(default=False, verbose_name=_('Is a fake code'))
|
|
841 |
|
836 |
842 |
@classmethod
|
837 |
843 |
def cleanup(cls, now=None):
|
838 |
844 |
now = now or timezone.now()
|
839 |
845 |
cls.objects.filter(expires__lte=now).delete()
|
840 |
846 |
|
841 |
847 |
@classmethod
|
842 |
|
def create(cls, phone, kind=None, expires=None, duration=None):
|
|
848 |
def create(cls, phone, user=None, kind=None, expires=None, fake=False, duration=None):
|
843 |
849 |
if not kind:
|
844 |
850 |
kind = cls.KIND_REGISTRATION
|
845 |
851 |
if not duration:
|
846 |
852 |
duration = cls.CODE_DURATION
|
847 |
853 |
expires = expires or (timezone.now() + datetime.timedelta(seconds=duration))
|
848 |
|
return cls.objects.create(kind=kind, phone=phone, expires=expires)
|
|
854 |
return cls.objects.create(kind=kind, user=user, phone=phone, expires=expires, fake=fake)
|
849 |
|
-
|