"""passbook OTP Forms""" from django import forms from django.contrib.admin.widgets import FilteredSelectMultiple from django.core.validators import RegexValidator from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from django_otp.models import Device from passbook.factors.forms import GENERAL_FIELDS from passbook.factors.otp.models import OTPFactor OTP_CODE_VALIDATOR = RegexValidator( r"^[0-9a-z]{6,8}$", _("Only alpha-numeric characters are allowed.") ) class PictureWidget(forms.widgets.Widget): """Widget to render value as img-tag""" def render(self, name, value, attrs=None, renderer=None): return mark_safe(f'') # nosec class OTPVerifyForm(forms.Form): """Simple Form to verify OTP Code""" order = ["code"] code = forms.CharField( label=_("Code"), validators=[OTP_CODE_VALIDATOR], widget=forms.TextInput(attrs={"autocomplete": "off", "placeholder": "Code"}), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # This is a little helper so the field is focused by default self.fields["code"].widget.attrs.update( {"autofocus": "autofocus", "autocomplete": "off"} ) class OTPSetupForm(forms.Form): """OTP Setup form""" title = _("Set up OTP") device: Device = None qr_code = forms.CharField( widget=PictureWidget, disabled=True, required=False, label=_("Scan this Code with your OTP App."), ) code = forms.CharField( label=_("Code"), validators=[OTP_CODE_VALIDATOR], widget=forms.TextInput(attrs={"placeholder": _("One-Time Password")}), ) tokens = forms.MultipleChoiceField(disabled=True, required=False) def clean_code(self): """Check code with new otp device""" if self.device is not None: if not self.device.verify_token(int(self.cleaned_data.get("code"))): raise forms.ValidationError(_("OTP Code does not match")) return self.cleaned_data.get("code") class OTPFactorForm(forms.ModelForm): """Form to edit OTPFactor instances""" class Meta: model = OTPFactor fields = GENERAL_FIELDS + ["enforced"] widgets = { "name": forms.TextInput(), "order": forms.NumberInput(), "policies": FilteredSelectMultiple(_("policies"), False), }