stages/otp_validate: Implement OTP Validation stage
This commit is contained in:
parent
9613fcde89
commit
7c191b0984
|
@ -1,7 +1,9 @@
|
|||
"""OTP Static stage"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PassbookStageOTPStaticConfig(AppConfig):
|
||||
"""OTP Static stage"""
|
||||
|
||||
name = "passbook.stages.otp_static"
|
||||
label = "passbook_stages_otp_static"
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
"""OTP Validation Stage"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PassbookStageOTPValidateConfig(AppConfig):
|
||||
"""OTP Validation Stage"""
|
||||
|
||||
name = "passbook.stages.otp_validate"
|
||||
label = "passbook_stages_otp_validate"
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
"""OTP Validate stage forms"""
|
||||
from django import forms
|
||||
from django.core.validators import RegexValidator
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_otp import match_token
|
||||
|
||||
from passbook.core.models import User
|
||||
from passbook.stages.otp_validate.models import OTPValidateStage
|
||||
|
||||
OTP_CODE_VALIDATOR = RegexValidator(
|
||||
|
@ -10,6 +13,9 @@ OTP_CODE_VALIDATOR = RegexValidator(
|
|||
|
||||
|
||||
class ValidationForm(forms.Form):
|
||||
"""OTP Validate stage forms"""
|
||||
|
||||
user: User
|
||||
|
||||
code = forms.CharField(
|
||||
label=_("Code"),
|
||||
|
@ -23,11 +29,22 @@ class ValidationForm(forms.Form):
|
|||
),
|
||||
)
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.user = user
|
||||
|
||||
def clean_code(self):
|
||||
pass
|
||||
"""Validate code against all confirmed devices"""
|
||||
code = self.cleaned_data.get("code")
|
||||
device = match_token(self.user, code)
|
||||
if not device:
|
||||
raise forms.ValidationError(_("Invalid Token"))
|
||||
return code
|
||||
|
||||
|
||||
class OTPValidateStageForm(forms.ModelForm):
|
||||
"""OTP Validate stage forms"""
|
||||
|
||||
class Meta:
|
||||
|
||||
model = OTPValidateStage
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""OTP Validation Stage"""
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""OTP Validate stage settings"""
|
||||
INSTALLED_APPS = [
|
||||
"django_otp",
|
||||
]
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from django.contrib import messages
|
||||
"""OTP Validation"""
|
||||
from typing import Any, Dict
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import FormView
|
||||
from django_otp import match_token, user_has_device
|
||||
from django_otp.models import Device
|
||||
from django_otp import user_has_device
|
||||
from structlog import get_logger
|
||||
|
||||
from passbook.flows.models import NotConfiguredAction, Stage
|
||||
from passbook.flows.models import NotConfiguredAction
|
||||
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from passbook.flows.stage import StageView
|
||||
from passbook.stages.otp_validate.forms import ValidationForm
|
||||
|
@ -16,9 +16,15 @@ LOGGER = get_logger()
|
|||
|
||||
|
||||
class OTPValidateStageView(FormView, StageView):
|
||||
"""OTP Validation"""
|
||||
|
||||
form_class = ValidationForm
|
||||
|
||||
def get_form_kwargs(self, **kwargs) -> Dict[str, Any]:
|
||||
kwargs = super().get_form_kwargs(**kwargs)
|
||||
kwargs["user"] = self.executor.plan.context.get(PLAN_CONTEXT_PENDING_USER)
|
||||
return kwargs
|
||||
|
||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
user = self.executor.plan.context.get(PLAN_CONTEXT_PENDING_USER)
|
||||
if not user:
|
||||
|
@ -35,11 +41,6 @@ class OTPValidateStageView(FormView, StageView):
|
|||
|
||||
def form_valid(self, form: ValidationForm) -> HttpResponse:
|
||||
"""Verify OTP Token"""
|
||||
device = match_token(
|
||||
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER],
|
||||
form.cleaned_data.get("code"),
|
||||
)
|
||||
if not device:
|
||||
messages.error(self.request, _("Invalid OTP."))
|
||||
return self.form_invalid(form)
|
||||
# Since we do token checking in the form, we know the token is valid here
|
||||
# so we can just continue
|
||||
return self.executor.stage_ok()
|
||||
|
|
Reference in New Issue