2019-02-25 11:29:40 +00:00
|
|
|
"""OTP Factor logic"""
|
|
|
|
from django.contrib import messages
|
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
from django.views.generic import FormView
|
|
|
|
from django_otp import match_token, user_has_device
|
2019-10-01 08:24:10 +00:00
|
|
|
from structlog import get_logger
|
2019-02-25 11:29:40 +00:00
|
|
|
|
2019-10-07 14:33:48 +00:00
|
|
|
from passbook.factors.otp.forms import OTPVerifyForm
|
|
|
|
from passbook.factors.otp.views import OTP_SETTING_UP_KEY, EnableView
|
2020-05-07 19:30:52 +00:00
|
|
|
from passbook.flows.factor_base import AuthenticationFactor
|
2020-05-08 14:10:27 +00:00
|
|
|
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER
|
2019-02-25 11:29:40 +00:00
|
|
|
|
2019-10-04 08:08:53 +00:00
|
|
|
LOGGER = get_logger()
|
2019-02-25 11:29:40 +00:00
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
|
2019-02-25 11:29:40 +00:00
|
|
|
class OTPFactor(FormView, AuthenticationFactor):
|
|
|
|
"""OTP Factor View"""
|
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
template_name = "otp/factor.html"
|
2019-02-25 11:29:40 +00:00
|
|
|
form_class = OTPVerifyForm
|
|
|
|
|
2019-02-25 12:02:50 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
kwargs = super().get_context_data(**kwargs)
|
2019-12-31 11:51:16 +00:00
|
|
|
kwargs["title"] = _("Enter Verification Code")
|
2019-02-25 12:02:50 +00:00
|
|
|
return kwargs
|
|
|
|
|
2019-02-25 11:29:40 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
"""Check if User has OTP enabled and if OTP is enforced"""
|
2020-05-08 14:10:27 +00:00
|
|
|
pending_user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
|
|
|
|
if not user_has_device(pending_user):
|
2019-02-25 11:29:40 +00:00
|
|
|
LOGGER.debug("User doesn't have OTP Setup.")
|
2020-05-08 14:10:27 +00:00
|
|
|
if self.executor.current_factor.enforced:
|
2019-02-25 11:29:40 +00:00
|
|
|
# Redirect to setup view
|
|
|
|
LOGGER.debug("OTP is enforced, redirecting to setup")
|
2020-05-08 14:10:27 +00:00
|
|
|
request.user = pending_user
|
2019-12-31 11:51:16 +00:00
|
|
|
messages.info(request, _("OTP is enforced. Please setup OTP."))
|
2019-02-25 12:02:50 +00:00
|
|
|
return EnableView.as_view()(request)
|
2019-02-25 11:29:40 +00:00
|
|
|
LOGGER.debug("OTP is not enforced, skipping form")
|
2020-05-08 14:10:27 +00:00
|
|
|
return self.executor.user_ok()
|
2019-02-25 11:29:40 +00:00
|
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
"""Check if setup is in progress and redirect to EnableView"""
|
|
|
|
if OTP_SETTING_UP_KEY in request.session:
|
|
|
|
LOGGER.debug("Passing POST to EnableView")
|
2020-05-08 14:10:27 +00:00
|
|
|
request.user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
|
2019-02-25 12:02:50 +00:00
|
|
|
return EnableView.as_view()(request)
|
2019-02-25 11:29:40 +00:00
|
|
|
return super().post(self, request, *args, **kwargs)
|
|
|
|
|
|
|
|
def form_valid(self, form: OTPVerifyForm):
|
|
|
|
"""Verify OTP Token"""
|
2020-05-08 14:10:27 +00:00
|
|
|
device = match_token(
|
|
|
|
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER],
|
|
|
|
form.cleaned_data.get("code"),
|
|
|
|
)
|
2019-02-25 11:29:40 +00:00
|
|
|
if device:
|
2020-05-08 14:10:27 +00:00
|
|
|
return self.executor.factor_ok()
|
2019-12-31 11:51:16 +00:00
|
|
|
messages.error(self.request, _("Invalid OTP."))
|
2019-02-25 11:29:40 +00:00
|
|
|
return self.form_invalid(form)
|