layerindex-web/layerindex/auth_views.py
Meh Mbeh Ida Delphine 2314fb2811 Add SPDX license headers to layerindex-web source files
Added SPDX identifiers to all .py files except those in migrations directory.

Fixes: [YOCTO #13527]

Signed-off-by: Meh Mbeh Ida Delphine <idadelm@gmail.com>
Signed-off-by: Paul Eggleton <bluelightning@bluelightning.org>
2021-04-21 08:22:51 +12:00

143 lines
6.2 KiB
Python

# layerindex-web - extended authentication views
#
# Copyright (C) 2018 Intel Corporation
#
# Licensed under the MIT license, see COPYING.MIT for details
#
# SPDX-License-Identifier: MIT
from django.contrib import messages
from django.contrib.auth import logout
from django.contrib.auth.hashers import make_password
from django.contrib.auth.views import (PasswordResetConfirmView,
PasswordResetView)
from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django_registration import signals
from django_registration.backends.activation.views import RegistrationView
from layerindex.auth_forms import (CaptchaPasswordResetForm,
CaptchaRegistrationForm, DeleteAccountForm,
SecurityQuestionPasswordResetForm)
from .models import SecurityQuestion, SecurityQuestionAnswer, UserProfile
from . import tasks
import settings
@method_decorator(never_cache, name='dispatch')
class CaptchaRegistrationView(RegistrationView):
form_class = CaptchaRegistrationForm
def register(self, form):
new_user = self.create_inactive_user(form)
signals.user_registered.send(
sender=self.__class__,
user=new_user,
request=self.request
)
# Add security question answers to the database
security_question_1 = SecurityQuestion.objects.get(question=form.cleaned_data.get("security_question_1"))
security_question_2 = SecurityQuestion.objects.get(question=form.cleaned_data.get("security_question_2"))
security_question_3 = SecurityQuestion.objects.get(question=form.cleaned_data.get("security_question_3"))
answer_1 = form.cleaned_data.get("answer_1").replace(" ", "").lower()
answer_2 = form.cleaned_data.get("answer_2").replace(" ", "").lower()
answer_3 = form.cleaned_data.get("answer_3").replace(" ", "").lower()
user = UserProfile.objects.create(user=new_user)
# Answers are hashed using Django's password hashing function make_password()
SecurityQuestionAnswer.objects.create(user=user, security_question=security_question_1,
answer=make_password(answer_1))
SecurityQuestionAnswer.objects.create(user=user, security_question=security_question_2,
answer=make_password(answer_2))
SecurityQuestionAnswer.objects.create(user=user, security_question=security_question_3,
answer=make_password(answer_3))
def get_context_data(self, **kwargs):
context = super(CaptchaRegistrationView, self).get_context_data(**kwargs)
form = context['form']
# Prepare a list of fields with errors
# We do this so that if there's a problem with the captcha, that's the only error shown
# (since we have a username field, we want to make user enumeration difficult)
if 'captcha' in form.errors:
error_fields = ['captcha']
else:
error_fields = form.errors.keys()
context['error_fields'] = error_fields
return context
@method_decorator(never_cache, name='dispatch')
class CaptchaPasswordResetView(PasswordResetView):
form_class = CaptchaPasswordResetForm
def delete_account_view(request, template_name):
if not request.user.is_authenticated:
raise PermissionDenied
if request.user.is_superuser:
# It's not really appropriate for the superuser to be deleted this way
raise PermissionDenied
if request.method == 'POST':
form = DeleteAccountForm(request.POST, instance=request.user)
if form.is_valid():
# Naturally we don't call form.save() here !
# Take a copy of request.user as it is about to be invalidated by logout()
user = request.user
logout(request)
user.delete()
messages.add_message(request, messages.SUCCESS,
'Your user account has been successfully deleted')
return HttpResponseRedirect(reverse('frontpage'))
else:
form = DeleteAccountForm(instance=request.user)
return render(request, template_name, {
'user': request.user,
'form': form,
})
class PasswordResetSecurityQuestions(PasswordResetConfirmView):
form_class = SecurityQuestionPasswordResetForm
def get(self, request, *args, **kwargs):
try:
self.user.userprofile
except UserProfile.DoesNotExist:
if getattr(settings, 'SECURITY_QUESTIONS_REQUIRED', True):
return HttpResponseRedirect(reverse('password_reset_fail'))
if not self.user.is_active:
return HttpResponseRedirect(reverse('account_lockout'))
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
form = self.form_class(data=request.POST, user=self.user)
form.is_valid()
for error in form.non_field_errors().as_data():
if error.code == "account_locked":
# Deactivate user's account.
self.user.is_active = False
self.user.save()
# Send admin an email that user is locked out.
site_name = get_current_site(request).name
subject = "User account locked on " + site_name
text_content = "User " + self.user.username + " has been locked out on " + site_name + "."
admins = settings.ADMINS
from_email = settings.DEFAULT_FROM_EMAIL
tasks.send_email.apply_async((subject, text_content, from_email, [a[1] for a in admins]))
return HttpResponseRedirect(reverse('account_lockout'))
if error.code == "incorrect_answers":
# User has failed first attempt at answering questions, give them another try.
return self.form_invalid(form)
return super().post(request, *args, **kwargs)