Added a settings change view for users in the frontend

This commit is contained in:
Raphael Michel
2015-06-25 20:57:02 +02:00
parent ae5eab628c
commit 11eb01a92b
11 changed files with 190 additions and 57 deletions

View File

@@ -0,0 +1,93 @@
import copy
from django.db import models
from django.forms.models import ModelFormMetaclass, BaseModelForm
from django import forms
from django.utils import six
from pretix.base.i18n import I18nFormField
from versions.models import Versionable
from django.utils.translation import ugettext_lazy as _
class BaseI18nModelForm(BaseModelForm):
"""
This is a helperclass to construct I18nModelForm
"""
def __init__(self, *args, **kwargs):
event = kwargs.pop('event', None)
super().__init__(*args, **kwargs)
if event:
for k, field in self.fields.items():
if isinstance(field, I18nFormField):
field.widget.enabled_langcodes = event.settings.get('locales')
class VersionedBaseModelForm(BaseI18nModelForm):
"""
This is a helperclass to construct VersionedModelForm
"""
def __init__(self, *args, **kwargs):
instance = kwargs.get('instance', None)
self.original_instance = copy.copy(instance) if instance else None
super().__init__(*args, **kwargs)
def save(self, commit=True):
if self.instance.pk is not None and isinstance(self.instance, Versionable):
if self.has_changed() and self.original_instance:
new = self.instance
old = self.original_instance
clone = old.clone()
for f in type(self.instance)._meta.get_fields():
if f.name not in (
'id', 'identity', 'version_start_date', 'version_end_date',
'version_birth_date'
) and not isinstance(f, (
models.ManyToOneRel, models.ManyToManyRel, models.ManyToManyField
)):
setattr(clone, f.name, getattr(new, f.name))
self.instance = clone
return super().save(commit)
class VersionedModelForm(six.with_metaclass(ModelFormMetaclass, VersionedBaseModelForm)):
"""
This is a modified version of I18nModelForm which differs from I18nModelForm in
only one way: It executes the .clone() method of an object before saving it back to
the database, if the model is a sub-class of versions.models.Versionable. You can
safely use this as a base class for all your model forms, it will work out correctly
with both versioned and non-versioned models.
"""
pass
class I18nModelForm(six.with_metaclass(ModelFormMetaclass, BaseI18nModelForm)):
"""
This is a modified version of Django's ModelForm which differs from ModelForm in
only one way: The constructor takes one additional optional argument ``event``
which may be given an :pyclass:`pretix.base.models.Event` instance. If given, this
instance is used to select the visible languages in all I18nFormFields of the form. If
not given, all languages will be displayed.
"""
pass
class SettingsForm(forms.Form):
"""
This form is meant to be used for modifying Event- or OrganizerSettings
"""
BOOL_CHOICES = (
('False', _('disabled')),
('True', _('enabled')),
)
def __init__(self, *args, **kwargs):
self.obj = kwargs.pop('obj')
kwargs['initial'] = self.obj.settings
super().__init__(*args, **kwargs)
def save(self):
for name, field in self.fields.items():
value = self.cleaned_data[name]
if value is None:
del self.obj.settings[name]
elif self.obj.settings.get(name, as_type=type(value)) != value:
self.obj.settings.set(name, value)

View File

@@ -0,0 +1,94 @@
from django import forms
from django.contrib.auth.hashers import check_password
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from pytz import common_timezones
from pretix.base.models import User
class UserSettingsForm(forms.ModelForm):
error_messages = {
'duplicate_identifier': _("There already is an account associated with this e-mail address. "
"Please choose a different one."),
'pw_current': _("Please enter your current password if you want to change your e-mail "
"address or password."),
'pw_current_wrong': _("The current password you entered was not correct."),
'pw_mismatch': _("Please enter the same password twice"),
}
old_pw = forms.CharField(max_length=255,
required=False,
label=_("Your current password"),
widget=forms.PasswordInput())
new_pw = forms.CharField(max_length=255,
required=False,
label=_("New password"),
widget=forms.PasswordInput())
new_pw_repeat = forms.CharField(max_length=255,
required=False,
label=_("Repeat new password"),
widget=forms.PasswordInput())
# timezone = forms.ChoiceField(
# choices=((a, a) for a in common_timezones),
# label=_("Default timezone"),
# )
class Meta:
model = User
fields = [
'givenname',
'familyname',
'locale',
# 'timezone',
'email'
]
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super().__init__(*args, **kwargs)
def clean_old_pw(self):
old_pw = self.cleaned_data.get('old_pw')
if old_pw and not check_password(old_pw, self.user.password):
raise forms.ValidationError(
self.error_messages['pw_current_wrong'],
code='pw_current_wrong',
)
return old_pw
def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(Q(identifier=email) & ~Q(pk=self.instance.pk)).exists():
raise forms.ValidationError(
self.error_messages['duplicate_identifier'],
code='duplicate_identifier',
)
return email
def clean_new_pw_repeat(self):
password1 = self.cleaned_data.get('new_pw')
password2 = self.cleaned_data.get('new_pw_repeat')
if password1 and password1 != password2:
raise forms.ValidationError(
self.error_messages['pw_mismatch'],
code='pw_mismatch'
)
def clean(self):
password1 = self.cleaned_data.get('new_pw')
email = self.cleaned_data.get('email')
old_pw = self.cleaned_data.get('old_pw')
if (password1 or email != self.user.email) and not old_pw:
raise forms.ValidationError(
self.error_messages['pw_current'],
code='pw_current'
)
if password1:
self.instance.set_password(password1)
self.instance.identifier = email
return self.cleaned_data