[A11y] Improve customer account forms (#5034)

This commit is contained in:
Richard Schreiber
2025-05-09 08:36:09 +02:00
committed by GitHub
parent 3e335bcbfe
commit 2b735bec0b
10 changed files with 210 additions and 118 deletions

View File

@@ -44,6 +44,7 @@ from pretix.base.forms.questions import (
from pretix.base.i18n import get_language_without_region
from pretix.base.models import Customer
from pretix.helpers.http import get_client_ip
from pretix.multidomain.urlreverse import build_absolute_uri
class TokenGenerator(PasswordResetTokenGenerator):
@@ -68,16 +69,24 @@ class AuthenticationForm(forms.Form):
'invalid_login': _(
"We have not found an account with this email address and password."
),
'invalid_login_email': _('Please verify that you entered the correct email addess.'),
'invalid_login_password': _('Please enter the correct password.'),
'inactive': _("This account is disabled."),
'unverified': _("You have not yet activated your account and set a password. Please click the link in the "
"email we sent you. Click \"Reset password\" to receive a new email in case you cannot find "
"it again."),
"email we sent you. In case you cannot find it, click \"Forgot your password?\" to receive "
"a new email."),
}
def __init__(self, request=None, *args, **kwargs):
self.request = request
self.customer_cache = None
super().__init__(*args, **kwargs)
self.fields['password'].help_text = "<a href='{}'>{}</a>".format(
build_absolute_uri(False, 'presale:organizer.customer.resetpw', kwargs={
'organizer': request.organizer.slug,
}),
_('Forgot your password?')
)
def clean(self):
email = self.cleaned_data.get('email')
@@ -94,6 +103,8 @@ class AuthenticationForm(forms.Form):
if u.check_password(password):
self.customer_cache = u
if self.customer_cache is None:
self.add_error("email", self.error_messages['invalid_login_email'])
self.add_error("password", self.error_messages['invalid_login_password'])
raise forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
@@ -110,15 +121,9 @@ class AuthenticationForm(forms.Form):
def confirm_login_allowed(self, user):
if not user.is_active:
raise forms.ValidationError(
self.error_messages['inactive'],
code='inactive',
)
if not user.is_verified:
raise forms.ValidationError(
self.error_messages['unverified'],
code='unverified',
)
self.add_error("email", self.error_messages['inactive'])
elif not user.is_verified:
self.add_error("password", self.error_messages['unverified'])
def get_customer(self):
return self.customer_cache

View File

@@ -48,15 +48,6 @@
</p>
{% if request.organizer.settings.customer_accounts_native %}
{% bootstrap_form login_form layout="checkout" %}
<div class="row">
<div class="col-md-offset-3 col-md-9">
<a
href="{% abseventurl request.organizer "presale:organizer.customer.resetpw" %}"
target="_blank">
{% trans "Reset password" %}
</a>
</div>
</div>
{% endif %}
<div class="row">
<div class="col-md-6 col-md-offset-3">

View File

@@ -6,19 +6,26 @@
{% block title %}{% trans "Account information" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% blocktrans trimmed %}
Update your account information
{% endblocktrans %}
</h2>
<form action="" method="post">
<div class="col-xs-12">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% trans "Save" %}
</button>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
{% trans "Update your account information" %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
</div>
</div>
<div class="row checkout-button-row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Save" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>

View File

@@ -7,48 +7,70 @@
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% if request.organizer.settings.customer_accounts_native %}
<form action="" method="post" class="form-horizontal blank-after">
{% csrf_token %}
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
{% blocktrans trimmed with org=request.organizer.name %}
Sign in to your account at {{ org }}
{% endblocktrans %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
<div class="row">
<div class="col-md-8 col-sm-6 hidden-xs">
<a class="btn btn-link btn-lg"
href="{% eventurl request.organizer "presale:organizer.customer.register" %}">
<small>
{% icon "address-book-o" %}
{% trans "Create account" %}
</small>
</a>
</div>
<div class="col-md-4 col-sm-6">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% icon "sign-in" %}
{% trans "Log in" %}
</button>
</div>
<div class="clearfix"></div>
</div>
<div class="row visible-xs">
<div class="col-xs-12 text-center"><br>
<a
href="{% eventurl request.organizer "presale:organizer.customer.register" %}">
{% icon "address-book-o" %}
{% trans "Create account" %}
</a>
</div>
</div>
</div>
</div>
</form>
{% else %}
<h2 class="blank-after">
{% blocktrans trimmed with org=request.organizer.name %}
Sign in to your account at {{ org }}
{% endblocktrans %}
</h2>
<form action="" method="post">
{% csrf_token %}
{% if request.organizer.settings.customer_accounts_native %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% icon "sign-in" %}
{% trans "Log in" %}
</button>
</div>
{% endif %}
</h2>
{% endif %}
{% if providers %}
<ul class="list-inline text-center blank-after">
{% for provider in providers %}
{% if provider.is_active %}
<li>
<a href="{% eventurl request.organizer "presale:organizer.customer.login" provider=provider.pk %}?{{ request.META.QUERY_STRING }}"
class="btn btn-primary btn-lg btn-block">
{{ provider.button_label }}
class="btn {% if request.organizer.settings.customer_accounts_native %}btn-default{% else %}btn-primary btn-lg btn-block{% endif %}">
{% icon "sign-in" %} {{ provider.button_label }}
</a>
{% endif %}
</li>
{% endfor %}
{% if request.organizer.settings.customer_accounts_native %}
<div class="row">
<div class="col-md-6">
<a class="btn btn-link btn-block"
href="{% eventurl request.organizer "presale:organizer.customer.register" %}">
{% icon "address-book-o" %}
{% trans "Create account" %}
</a>
</div>
<div class="col-md-6">
<a class="btn btn-link btn-block"
href="{% eventurl request.organizer "presale:organizer.customer.resetpw" %}">
{% trans "Reset password" %}
</a>
</div>
</div>
{% endif %}
</form>
</ul>
{% endif %}
</div>
</div>
<p>&nbsp;</p>

View File

@@ -7,18 +7,25 @@
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% blocktrans trimmed %}
Set a new password for your account
{% endblocktrans %}
</h2>
<form action="" method="post">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% trans "Save" %}
</button>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
{% trans "Set a new password for your account" %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
</div>
</div>
<div class="row checkout-button-row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Save" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>

View File

@@ -1,28 +1,54 @@
{% extends "pretixpresale/organizers/base.html" %}
{% load i18n %}
{% load icon %}
{% load eventurl %}
{% load urlreplace %}
{% load bootstrap3 %}
{% block title %}{% trans "Registration" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% blocktrans trimmed with org=request.organizer.name %}
Create a new account at {{ org }}
{% endblocktrans %}
</h2>
<form action="" method="post">
<div class="col-xs-12">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% trans "Create account" %}
</button>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
{% blocktrans trimmed with org=request.organizer.name %}
Create a new account at {{ org }}
{% endblocktrans %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
</div>
</div>
<div class="row checkout-button-row blank-after">
<div class="col-md-8 col-sm-6 hidden-xs">
<a class="btn btn-link btn-lg"
href="{% eventurl request.organizer "presale:organizer.customer.login" %}">
<small>
{% icon "sign-in" %}
{% trans "Log in to an existing account" %}
</small>
</a>
</div>
<div class="col-md-4 col-sm-6">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% icon "address-book-o" %}
{% trans "Create account" %}
</button>
</div>
<div class="clearfix"></div>
</div>
<div class="row visible-xs">
<div class="col-xs-12 text-center">
<a
href="{% eventurl request.organizer "presale:organizer.customer.login" %}">
{% icon "sign-in" %}
{% trans "Log in to an existing account" %}
</a>
</div>
</div>
<a class="btn btn-link btn-block" href="{% eventurl request.organizer "presale:organizer.customer.login" %}">
{% trans "Log in to an existing account" %}
</a>
</form>
</div>
</div>

View File

@@ -1,5 +1,6 @@
{% extends "pretixpresale/organizers/base.html" %}
{% load i18n %}
{% load icon %}
{% load eventurl %}
{% load urlreplace %}
{% load bootstrap3 %}
@@ -7,18 +8,44 @@
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% blocktrans trimmed %}
Password reset
{% endblocktrans %}
</h2>
<form action="" method="post">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% trans "Request a new password" %}
</button>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
{% trans "Request a new password" %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
<div class="row">
<div class="col-sm-4 hidden-xs">
<a class="btn btn-link btn-lg"
href="{% eventurl request.organizer "presale:organizer.customer.login" %}">
<small>
{% icon "sign-in" %}
{% trans "Log in" %}
</small>
</a>
</div>
<div class="col-sm-8">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Request a new password" %}
</button>
</div>
<div class="clearfix"></div>
</div>
<div class="row visible-xs">
<div class="col-xs-12 text-center">
<a
href="{% eventurl request.organizer "presale:organizer.customer.register" %}">
{% icon "sign-in" %}
{% trans "Log in" %}
</a>
</div>
</div>
</div>
</div>
</form>
</div>

View File

@@ -7,18 +7,25 @@
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h2>
{% blocktrans trimmed %}
Set a new password for your account
{% endblocktrans %}
</h2>
<form action="" method="post">
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group buttons">
<button type="submit" class="btn btn-primary btn-lg btn-block">
{% trans "Save" %}
</button>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
{% trans "Set a new password for your account" %}
</h2>
</div>
<div class="panel-body">
{% bootstrap_form form layout="checkout" %}
</div>
</div>
<div class="row checkout-button-row blank-after">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Save" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>

View File

@@ -122,7 +122,7 @@ class LoginView(RedirectBackMixin, FormView):
def get_context_data(self, **kwargs):
return super().get_context_data(
**kwargs,
providers=self.request.organizer.sso_providers.all()
providers=self.request.organizer.sso_providers.filter(is_active=True)
)
def get_form_kwargs(self):

View File

@@ -239,7 +239,7 @@ def test_org_login_not_verified(env, client, mocker):
'password': 'foo',
})
assert r.status_code == 200
assert b'alert-danger' in r.content
assert b'form-group has-error' in r.content
customer_signed_in.send.assert_not_called()
@@ -258,7 +258,7 @@ def test_org_login_not_active(env, client, mocker):
'password': 'foo',
})
assert r.status_code == 200
assert b'alert-danger' in r.content
assert b'form-group has-error' in r.content
customer_signed_in.send.assert_not_called()