I have a website and I have already redefined the user model, made authorization/registration via email. Now I want to do authorization when a user enters a username, password and a confirmation code is sent to his email. I am interested in the scheme of work. I see it this way: vyushka generates code using random, send_email sends it and this very code is written to the database. In my opinion, this is a bad decision (For example, to store the code in the database with the user, because you still have to implement the expiration date, etc.). So, are there any options for how this can be done. (generate code, where and how to store it for verification). I know about all sorts of libraries with 2FA, this is not my option.
You can create a TwoFactorEmailModel class with code, expiration, created_at and user fields, when the user enters email, password and the code sent to him, you have to sort all the TwoFactorEmailModel objects of this user by created_at field and get the first object, if it has not expired and the user entered code is equal to the object code, then you can authenticate the user.
Edit:
Вы можете создать метод модели(описаной выше), который будет генерироваь код(вообще я уверен что для этого есть готовая библиотека) и вызыватся при инициализации модели то есть в методе init, а затем создать ещё один метод, который будет отправлять электронное письмо пользователю. Например методы могут выглядеть так:
class TwoFactorEmailModel(models.Model):
code = models.CharField(max_length=32)
created_at = models.DateTimeField(auto_now_add=True)
expiration = models.DateTimeField(default=now() + timedelta(hours=2))
user = models.ForeignKey(to='users.User', on_delete=models.CASCADE)
def save(self):
self.code = generate_code()
return super().save()
def generate_code(self):
return 'your logic here'
def send_two_factor_email(self, subject, body):
'your logic...'
send_mail(subject, body, [self.user.email])
def can_be_sent(self, code):
return self.expiration < now() and self.code == code
def is_expired(self):
return self.expiration < now()