diff --git a/src/pretix/control/forms/auth.py b/src/pretix/control/forms/auth.py new file mode 100644 index 0000000000..0b397c1e02 --- /dev/null +++ b/src/pretix/control/forms/auth.py @@ -0,0 +1,83 @@ +from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm +from django import forms +from django.utils.translation import ugettext as _ +from django.contrib.auth import authenticate +from pretix.base.models import User + + +class AuthenticationForm(BaseAuthenticationForm): + """ + The login form, providing an email and password field. The form already implements + validation for correct user data. + """ + email = forms.EmailField(label=_("Email address"), max_length=254) + password = forms.CharField(label=_("Password"), widget=forms.PasswordInput) + username = None + + error_messages = { + 'invalid_login': _("Please enter a correct e-mail address and password."), + 'inactive': _("This account is inactive.") + } + + def __init__(self, request=None, *args, **kwargs): + self.request = request + self.user_cache = None + super(forms.Form, self).__init__(*args, **kwargs) + + def clean(self): + email = self.cleaned_data.get('email') + password = self.cleaned_data.get('password') + + if email and password: + self.user_cache = authenticate(identifier=email.lower(), + password=password) + if self.user_cache is None: + raise forms.ValidationError( + self.error_messages['invalid_login'], + code='invalid_login' + ) + else: + self.confirm_login_allowed(self.user_cache) + + return self.cleaned_data + + +class GlobalRegistrationForm(forms.Form): + error_messages = { + 'duplicate_email': _("You already registered with that e-mail address, please use the login form."), + 'pw_mismatch': _("Please enter the same password twice") + } + email = forms.EmailField( + label=_('Email address'), + required=True + ) + password = forms.CharField( + label=_('Password'), + widget=forms.PasswordInput, + required=True + ) + password_repeat = forms.CharField( + label=_('Repeat password'), + widget=forms.PasswordInput + ) + + def clean(self): + password1 = self.cleaned_data.get('password') + password2 = self.cleaned_data.get('password_repeat') + + if password1 and password1 != password2: + raise forms.ValidationError( + self.error_messages['pw_mismatch'], + code='pw_mismatch', + ) + + return self.cleaned_data + + def clean_email(self): + email = self.cleaned_data['email'] + if User.objects.filter(identifier=email).exists(): + raise forms.ValidationError( + self.error_messages['duplicate_email'], + code='duplicate_email', + ) + return email diff --git a/src/pretix/control/middleware.py b/src/pretix/control/middleware.py index 2509466b1a..34d966899a 100644 --- a/src/pretix/control/middleware.py +++ b/src/pretix/control/middleware.py @@ -19,7 +19,8 @@ class PermissionMiddleware: """ EXCEPTIONS = ( - "auth.login" + "auth.login", + "auth.register" ) def process_request(self, request): diff --git a/src/pretix/control/static/pretixcontrol/less/auth.less b/src/pretix/control/static/pretixcontrol/less/auth.less index adfc5e2ac4..a91fa5b8f3 100644 --- a/src/pretix/control/static/pretixcontrol/less/auth.less +++ b/src/pretix/control/static/pretixcontrol/less/auth.less @@ -25,4 +25,8 @@ footer { .buttons { text-align: right; } + + h3 { + margin-top: 0; + } } diff --git a/src/pretix/control/templates/pretixcontrol/auth/login.html b/src/pretix/control/templates/pretixcontrol/auth/login.html index 3860230876..5c54d27775 100644 --- a/src/pretix/control/templates/pretixcontrol/auth/login.html +++ b/src/pretix/control/templates/pretixcontrol/auth/login.html @@ -8,6 +8,10 @@ {% bootstrap_field form.email %} {% bootstrap_field form.password %}
+ + {% trans "Register" %} + + diff --git a/src/pretix/control/templates/pretixcontrol/auth/register.html b/src/pretix/control/templates/pretixcontrol/auth/register.html new file mode 100644 index 0000000000..84cc8afa0f --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/auth/register.html @@ -0,0 +1,22 @@ +{% extends "pretixcontrol/auth/base.html" %} +{% load bootstrap3 %} +{% load i18n %} +{% block content %} +
+

{% trans "Create a new account" %}

+ {% bootstrap_form_errors form type='all' layout='inline' %} + {% csrf_token %} + {% bootstrap_field form.email %} + {% bootstrap_field form.password %} + {% bootstrap_field form.password_repeat %} +
+ + « {% trans "Login" %} + + + +
+
+{% endblock %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index fb32c615a7..859b0fa960 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -6,6 +6,7 @@ from pretix.control.views import main, event, item, auth, orders, user, organize urlpatterns = [ url(r'^logout$', auth.logout, name='auth.logout'), url(r'^login$', auth.login, name='auth.login'), + url(r'^register$', auth.register, name='auth.register'), url(r'^$', main.index, name='index'), url(r'^settings$', user.UserSettings.as_view(), name='user.settings'), url(r'^organizers/$', organizer.OrganizerList.as_view(), name='organizers'), diff --git a/src/pretix/control/views/auth.py b/src/pretix/control/views/auth.py index 480a396ad1..9e3a763fef 100644 --- a/src/pretix/control/views/auth.py +++ b/src/pretix/control/views/auth.py @@ -1,47 +1,9 @@ +from django.conf import settings from django.shortcuts import render, redirect -from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm -from django import forms -from django.utils.translation import ugettext as _ -from django.contrib.auth import authenticate -from django.contrib.auth import login as auth_login +from django.contrib.auth import login as auth_login, authenticate from django.contrib.auth import logout as auth_logout - - -class AuthenticationForm(BaseAuthenticationForm): - """ - The login form, providing an email and password field. The form already implements - validation for correct user data. - """ - email = forms.EmailField(label=_("E-mail address"), max_length=254) - password = forms.CharField(label=_("Password"), widget=forms.PasswordInput) - username = None - - error_messages = { - 'invalid_login': _("Please enter a correct e-mail address and password."), - 'inactive': _("This account is inactive."), - } - - def __init__(self, request=None, *args, **kwargs): - self.request = request - self.user_cache = None - super(forms.Form, self).__init__(*args, **kwargs) - - def clean(self): - email = self.cleaned_data.get('email') - password = self.cleaned_data.get('password') - - if email and password: - self.user_cache = authenticate(identifier=email.lower(), - password=password) - if self.user_cache is None: - raise forms.ValidationError( - self.error_messages['invalid_login'], - code='invalid_login', - ) - else: - self.confirm_login_allowed(self.user_cache) - - return self.cleaned_data +from pretix.base.models import User +from pretix.control.forms.auth import AuthenticationForm, GlobalRegistrationForm def login(request): @@ -73,3 +35,29 @@ def logout(request): """ auth_logout(request) return redirect('control:auth.login') + + +def register(request): + """ + Render and process a basic registration form. + """ + ctx = {} + if request.user.is_authenticated(): + if "next" in request.GET: + return redirect(request.GET.get("next", 'control:index')) + return redirect('control:index') + if request.method == 'POST': + form = GlobalRegistrationForm(data=request.POST) + if form.is_valid(): + user = User.objects.create_global_user( + form.cleaned_data['email'], form.cleaned_data['password'], + locale=request.LANGUAGE_CODE, + timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE + ) + user = authenticate(identifier=user.identifier, password=form.cleaned_data['password']) + auth_login(request, user) + return redirect('control:index') + else: + form = GlobalRegistrationForm() + ctx['form'] = form + return render(request, 'pretixcontrol/auth/register.html', ctx) diff --git a/src/pretix/presale/views/event.py b/src/pretix/presale/views/event.py index 49b3a88e2e..41d84a8305 100644 --- a/src/pretix/presale/views/event.py +++ b/src/pretix/presale/views/event.py @@ -110,7 +110,7 @@ class EventLogin(EventViewMixin, TemplateView): request.event, form.cleaned_data['username'], form.cleaned_data['password'], email=form.cleaned_data['email'] if form.cleaned_data['email'] != '' else None, locale=request.LANGUAGE_CODE, - timezone=request.timezone if hasattr(request, 'timezone') else None + timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE ) user = authenticate(identifier=user.identifier, password=form.cleaned_data['password']) login(request, user) @@ -121,7 +121,7 @@ class EventLogin(EventViewMixin, TemplateView): user = User.objects.create_global_user( form.cleaned_data['email'], form.cleaned_data['password'], locale=request.LANGUAGE_CODE, - timezone=request.timezone if hasattr(request, 'timezone') else None + timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE ) user = authenticate(identifier=user.identifier, password=form.cleaned_data['password']) login(request, user)