117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
import logging
|
|
import secrets
|
|
from django.apps import apps
|
|
from django.core.exceptions import ValidationError
|
|
from django.contrib import messages
|
|
from django.contrib.auth import views as auth_views, get_user_model
|
|
from django.contrib.auth.password_validation import validate_password
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import resolve_url
|
|
from django.template.loader import render_to_string
|
|
from django.urls import reverse_lazy, reverse
|
|
from django.utils.safestring import mark_safe
|
|
from django.utils.translation import gettext as _
|
|
from django.views import generic
|
|
|
|
from . import emails
|
|
from . import forms
|
|
|
|
app_config = apps.get_containing_app_config(__package__)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class LoginView(auth_views.LoginView):
|
|
form_class = forms.LoginForm
|
|
template_name = 'dav_auth/forms/login.html'
|
|
weak_password_warning_template_name = 'dav_auth/includes/weak_password_warning.html'
|
|
|
|
def get_redirect_url(self):
|
|
url = super().get_redirect_url()
|
|
if not url and app_config.settings.login_redirect_url:
|
|
url = resolve_url(app_config.settings.login_redirect_url)
|
|
return url
|
|
|
|
def form_valid(self, form):
|
|
r = super().form_valid(form)
|
|
messages.success(self.request, _('Benutzer angemeldet: %(username)s') % {'username': form.get_user()})
|
|
try:
|
|
validate_password(form.cleaned_data['password'])
|
|
except ValidationError as e:
|
|
logger.warning('Detected weak password for user id %d: %s', self.request.user.pk, e)
|
|
message = render_to_string(self.weak_password_warning_template_name)
|
|
messages.warning(self.request, mark_safe(message))
|
|
return r
|
|
|
|
|
|
class LogoutView(auth_views.LogoutView):
|
|
@property
|
|
def next_page(self):
|
|
url = None
|
|
if app_config.settings.logout_redirect_url:
|
|
url = resolve_url(app_config.settings.logout_redirect_url)
|
|
return url
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
r = super().dispatch(request, *args, **kwargs)
|
|
messages.success(self.request, _('Benutzer abgemeldet.'))
|
|
return r
|
|
|
|
|
|
class SetPasswordView(auth_views.PasswordChangeView):
|
|
form_class = forms.SetPasswordForm
|
|
template_name = 'dav_auth/forms/set_password.html'
|
|
|
|
def get_success_url(self):
|
|
return resolve_url(app_config.settings.login_redirect_url)
|
|
|
|
def form_valid(self, form):
|
|
r = super().form_valid(form)
|
|
messages.success(self.request, _('Passwort gespeichert.'))
|
|
logger.info('Changed password for user \'%s\'', self.request.user)
|
|
if form.cleaned_data.get('send_password_mail', False):
|
|
email = emails.PasswordSetEmail(self.request.user, form.cleaned_data['new_password'])
|
|
email.send()
|
|
return r
|
|
|
|
|
|
class CreateAndSendPasswordView(generic.FormView):
|
|
form_class = forms.CreateAndSendPasswordForm
|
|
template_name = 'dav_auth/forms/recreate_password.html'
|
|
success_url = reverse_lazy('dav_auth:login')
|
|
|
|
@staticmethod
|
|
def _create_new_password(length=None, characters=None):
|
|
if length is None:
|
|
length = app_config.settings.auto_password_length
|
|
if characters is None:
|
|
characters = app_config.settings.auto_password_characters
|
|
return ''.join(secrets.choice(characters) for i in range(length))
|
|
|
|
def form_valid(self, form):
|
|
username = form.cleaned_data.get('username')
|
|
user_model = get_user_model()
|
|
|
|
# Generate a new password (even if the user does not exist, to avoid revealing that fact).
|
|
random_password = self._create_new_password()
|
|
|
|
try:
|
|
user = user_model.objects.get(username=username)
|
|
user.set_password(random_password)
|
|
user.save()
|
|
email = emails.PasswordSetEmail(user, random_password)
|
|
email.send()
|
|
logger.info('Recreated password for user \'%s\'', username)
|
|
except user_model.DoesNotExist:
|
|
logger.warning('Recreated password for unknown user \'%s\'', username)
|
|
|
|
# Show message, that we sent an email, even we did not, so we do not reveal that the user doesn't exist.
|
|
messages.success(self.request, _('Neues Passwort versendet.'))
|
|
|
|
return super().form_valid(form)
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
if request.user.is_authenticated:
|
|
return HttpResponseRedirect(reverse('dav_auth:set_password'))
|
|
return super().get(request, *args, **kwargs)
|