Password and User settings Form implemented

This commit is contained in:
Dirk Alders 2024-10-27 19:04:17 +01:00
parent b63cfaa741
commit f31771b588
6 changed files with 138 additions and 49 deletions

View File

@ -1,7 +1,9 @@
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import UserProfile
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordChangeForm
from django.utils.translation import gettext as _
from .models import UserProfile, get_userprofile
from users import emails
class UserRegistrationForm(UserCreationForm):
@ -24,6 +26,72 @@ class UserProfileFormLanguageOnly(forms.ModelForm):
fields = ['language_code']
class UserPasswordChangeForm(PasswordChangeForm):
email = forms.EmailField()
first_name = forms.CharField(max_length=150)
last_name = forms.CharField(max_length=150)
field_order = ["email", "first_name", "last_name", "old_password", "new_password1", "new_password2"]
def __init__(self, request):
self.request = request
#
data = request.POST or {'email': request.user.email, 'first_name': request.user.first_name, 'last_name': request.user.last_name}
#
super().__init__(request.user, data)
self.fields['old_password'].widget.attrs.update({'autofocus': False})
self.fields['old_password'].required = False
def clean_old_password(self):
"""
Validation of old_password field only, if set.
"""
old_password = self.cleaned_data["old_password"]
if old_password and not self.user.check_password(old_password):
raise forms.ValidationError(
self.error_messages["password_incorrect"],
code="password_incorrect",
)
return old_password
def clean(self):
"""
Validation of new_passwords only if old_password field is set.
"""
clean_data = forms.Form.clean(self)
old_password = clean_data.get('old_password')
#
if old_password:
self.validate_passwords("new_password1", "new_password2")
self.validate_password_for_user(self.user, "new_password2")
return forms.Form.clean(self)
def save(self, commit=True):
changed = False
for key in self.fields:
new = self.data.get(key)
try:
old = getattr(self.user, key)
except AttributeError:
pass # Is a password field
else:
if new != old:
if key == 'email':
emails.send_validation_mail(self.user, self.request)
up = get_userprofile(self.user)
up.mail_pending = new
up.save()
else:
changed = True
setattr(self.user, key, new)
if self.data.get('new_password1'):
changed = True
self.user.set_password(self.data.get('new_password1'))
#
if changed:
self.user.save()
return changed
class UserActivationForm(UserChangeForm):
password = None

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-10-27 17:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0003_userprofile_mail_validated'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='mail_pending',
field=models.EmailField(max_length=254, null=True),
),
]

View File

@ -30,6 +30,7 @@ class UserProfile(models.Model):
timezone = models.CharField(max_length=150, default='UTC', choices=[(t, t) for t in pytz.common_timezones])
language_code = models.CharField(max_length=150, default='en', choices=settings.LANGUAGES)
mail_validated = models.BooleanField(default=False)
mail_pending = models.EmailField(null=True)
def export_key(self):
return self.user.username

View File

@ -4,7 +4,14 @@
{% block content %}
<form action="" method="post">
{% csrf_token %}
{% include 'users/profile_formdata.html' %}
{% get_current_language as LANGUAGE_CODE %}
<h1>{% trans "Language and Timezone" %}</h1>
{{ form_userprofile.as_p }}
<h1>{% trans "Userdata and Password" %}</h1>
{{ form_userchange.as_p }}
<input type="submit" value="{% trans "Save" %}" class="button" />
</form>

View File

@ -1,6 +0,0 @@
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
<h1>{% trans "Language and Timezone" %}</h1>
{{ form_userprofile.as_p }}
</select>

View File

@ -11,7 +11,7 @@ from django.contrib.auth.models import User
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_decode
from django.utils.translation import gettext as _
from .forms import UserRegistrationForm, UserProfileForm, UserActivationForm
from .forms import UserRegistrationForm, UserProfileForm, UserActivationForm, UserPasswordChangeForm
import logging
from .models import get_userprofile
from themes import Context
@ -28,35 +28,26 @@ def password_recovery(request):
return redirect(request.GET.get('next') or '/')
def profile_post_actions(request, context):
if request.POST:
form = context.get('form_userprofile')
if form.is_valid():
form.save()
return redirect(request.GET.get('next') or '/')
def profile_pre_actions(request, context, form_to_be_used=UserProfileForm):
profile = get_userprofile(request.user)
if request.POST:
form = form_to_be_used(request.POST, instance=profile)
else:
form = form_to_be_used(instance=profile)
context['form_userprofile'] = form
@login_required
def profile(request):
context = Context(request) # needs to be executed first because of time mesurement
profile_pre_actions(request, context)
response = profile_post_actions(request, context)
if response is not None:
return response
profile = get_userprofile(request.user)
if request.POST:
form_userprofile = UserProfileForm(request.POST, instance=profile)
form_userchange = UserPasswordChangeForm(request)
if form_userprofile.is_valid() and form_userchange.is_valid():
form_userprofile.save()
form_userchange.save()
return redirect(request.GET.get('next') or '/')
else:
form_userprofile = UserProfileForm(instance=profile)
form_userchange = UserPasswordChangeForm(request)
context_adaption(
context,
request,
_('Profile for %(username)s') % {'username': request.user.username},
form_userprofile=form_userprofile,
form_userchange=form_userchange,
)
return render(request, 'users/profile.html', context=context)
@ -158,6 +149,16 @@ def validate(request, uidb64, token):
myuser = None
if myuser is not None and generate_token.check_token(myuser, token):
up = get_userprofile(myuser)
if up.mail_pending:
# change of email-address
myuser.email = up.mail_pending
myuser.save()
up.mail_pending = None
up.save()
messages.success(request, _("Your new email address is now active."))
return redirect("/")
else:
# Store mail validation to user profile
profile = get_userprofile(myuser)
profile.mail_validated = True