Как ограничить пользователя только тремя неправильными otp-записями

Я заставляю своего пользователя вводить otp, который он получает по электронной почте. Но почему-то я не могу сделать цикл, который ограничит его вводить неправильный otp только 3 раза. Если он введет otp неправильно в третий раз, его имя пользователя будет удалено. вот код, который я написал

def registerpage(request):
    if request.method == 'POST':
        get_otp = request.POST.get('otp')
        if get_otp:
            get_user= request.POST.get('user')
            user = User.objects.get(username=get_user)

            if int(get_otp) == UserOtp.objects.filter(user= user).last().otp:
                user.is_active = True
                user.save()
                messages.success(request,'Login to complete the registration process.')
                return redirect('login')
            
            else:
               
                messages.error(request, f'OTP entered is wrong')
                return render(request, 'register.html', {'otp': True, 'user': user})



        first_name = request.POST['first_name']
        username = request.POST['email']
        password1= request.POST['password']
        password2= request.POST['con_password']
        email= request.POST['email']
        last_name= request.POST['join_as']

        if password1==password2:
            if User.objects.filter(username=username).exists():
                messages.info(request, 'UserID already exists')
                return redirect('register')
            elif User.objects.filter(email=email).exists():
                messages.info(request, 'Email already exists')
                return redirect('register')
            else:    
                user=User.objects.create_user(username= username.lower(), password= password1, email= email.lower(), first_name= first_name.upper(), last_name=last_name)
                user.is_active = False
                user.save()
                user_otp = random.randint(100000, 999999)
                UserOtp.objects.create(user =  user, otp = user_otp)
                mess = f"Hello, {user.first_name}, \nYour OTP is {user_otp}\n Thanks!"

                send_mail(
                    "Welcome to Solve Litigation - Verify your Email",   #subject
                    mess,  #message
                    settings.EMAIL_HOST_USER,  # sender
                    [user.email],           #reciever
                    fail_silently= False
                )

                return render(request, 'register.html', {'otp': True, 'user': user})


        else:
            messages.info(request, 'Password and Confirm Password not matching')
            return redirect('register') 

      
       
    
    else:
        return render(request, 'register.html')

models.py

class UserOtp(models.Model):
    user = models.ForeignKey(User, on_delete= models.CASCADE)
    time_stamp = models.DateTimeField(auto_now= True)
    otp = models.IntegerField()

Я пытался реализовать цикл while и for, но моя логика была неправильной, возможно, и я не получил желаемых результатов, поэтому я убрал циклы на время.

Вы можете хранить количество раз, когда UserOtp был ошибочным, с помощью целочисленного поля:

class UserOtp(models.Model):
    user = models.ForeignKey(User, on_delete= models.CASCADE)
    time_stamp = models.DateTimeField(auto_now= True)
    otp = models.IntegerField()
    wrongs = models.IntegerField(default=0)

В случае если последний UserOtp для данного пользователя был wrongs=2 и otp снова ошибочен, можно удалить объект user:

from django.db.models import F

# ⋮

if get_otp:
    user = User.objects.get(username=request.POST['user'])
    lastotp = UserOtp.objects.filter(user= user).last()
    if int(get_otp) == lastotp.otp:
        user.is_active = True
        user.save()
        messages.success(request,'Login to complete the registration process.')
        return redirect('login')
    elif lastotp.wrongs >= 2:
        user.delete()
        return redirect('name-of-some-view')
    else:
        lastotp.wrongs = F('wrongs') + 1
        lastotp.save(force_update=True, update_fields=['wrongs'])
        messages.error(request, f'OTP entered is wrong')
        return render(request, 'register.html', {'otp': True, 'user': user})

Если попытка таким образом не удалась, это увеличит поле wrongs на единицу. Если в поле wrongs будет две попытки и совпадение OTP снова будет неверным, мы используем user.delete() для удаления пользователя.

Однако это представление имеет брешь в безопасности: пользователь может удалить учетные записи других пользователей, просто сделав поддельные POST-запросы с тем же пользователем. Если Алиса, например, хочет удалить Боба, ей достаточно сделать три запроса к представлению с Бобом в качестве поля user, и тогда учетная запись Боба будет удалена.

Вернуться на верх