mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Added password reset to control.auth
This commit is contained in:
@@ -20,7 +20,9 @@ class PermissionMiddleware:
|
||||
|
||||
EXCEPTIONS = (
|
||||
"auth.login",
|
||||
"auth.register"
|
||||
"auth.register",
|
||||
"auth.forgot",
|
||||
"auth.forgot.recover"
|
||||
)
|
||||
|
||||
def process_request(self, request):
|
||||
|
||||
@@ -3,24 +3,34 @@
|
||||
{% load staticfiles %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ settings.PRETIX_INSTANCE_NAME }}</title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/less" href="{% static "pretixcontrol/less/auth.less" %}" />
|
||||
{% endcompress %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<footer>
|
||||
{% with "href='http://pretix.eu'" as a_attr %}
|
||||
{% blocktrans trimmed %}
|
||||
powered by <a {{ a_attr }}>pretix</a>
|
||||
{% endblocktrans %}
|
||||
{% endwith %}
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
<head>
|
||||
<title>{{ settings.PRETIX_INSTANCE_NAME }}</title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/less" href="{% static "pretixcontrol/less/auth.less" %}"/>
|
||||
{% endcompress %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<a href="{% url "control:auth.login" %}">
|
||||
<img src="{% static "pretixbase/img/pretix-logo.svg" %}" class="logo"/>
|
||||
</a>
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<footer>
|
||||
{% with "href='http://pretix.eu'" as a_attr %}
|
||||
{% blocktrans trimmed %}
|
||||
powered by <a {{ a_attr }}>pretix</a>
|
||||
{% endblocktrans %}
|
||||
{% endwith %}
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
18
src/pretix/control/templates/pretixcontrol/auth/forgot.html
Normal file
18
src/pretix/control/templates/pretixcontrol/auth/forgot.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% extends "pretixcontrol/auth/base.html" %}
|
||||
{% load bootstrap3 %}
|
||||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<form class="form-signin" action="" method="post">
|
||||
<h3>{% trans "Password recovery" %}</h3>
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
{% bootstrap_field form.email %}
|
||||
<div class="form-group buttons">
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Send recovery information" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -3,20 +3,25 @@
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% block content %}
|
||||
<img src="{% static "pretixbase/img/pretix-logo.svg" %}" class="logo" />
|
||||
<form class="form-signin" action="" method="post">
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
{% csrf_token %}
|
||||
{% bootstrap_field form.email %}
|
||||
{% bootstrap_field form.password %}
|
||||
<div class="form-group buttons">
|
||||
<form class="form-signin" action="" method="post">
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
{% csrf_token %}
|
||||
{% bootstrap_field form.email %}
|
||||
{% bootstrap_field form.password %}
|
||||
<div class="form-group buttons">
|
||||
<a href="{% url "control:auth.forgot" %}" class="btn btn-link">
|
||||
{% trans "Lost password?" %}
|
||||
</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Log in" %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group buttons">
|
||||
<a href="{% url "control:auth.register" %}" class="btn btn-link">
|
||||
{% trans "Register" %}
|
||||
</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Log in" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
19
src/pretix/control/templates/pretixcontrol/auth/recover.html
Normal file
19
src/pretix/control/templates/pretixcontrol/auth/recover.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{% extends "pretixcontrol/auth/base.html" %}
|
||||
{% load bootstrap3 %}
|
||||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<form class="form-signin" action="" method="post">
|
||||
<h3>{% trans "Set new password" %}</h3>
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
{% bootstrap_field form.password %}
|
||||
{% bootstrap_field form.password_repeat %}
|
||||
<div class="form-group buttons">
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -3,7 +3,6 @@
|
||||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<img src="{% static "pretixbase/img/pretix-logo.svg" %}" class="logo" />
|
||||
<form class="form-signin" action="" method="post">
|
||||
<h3>{% trans "Create a new account" %}</h3>
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{% load i18n %}{% blocktrans with url=url|safe %}Hello,
|
||||
|
||||
you requested a new password. Please go to the following page to reset your password:
|
||||
|
||||
{{ url }}
|
||||
|
||||
Best regards,
|
||||
Your pretix team
|
||||
{% endblocktrans %}
|
||||
@@ -8,6 +8,8 @@ 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'^forgot$', auth.Forgot.as_view(), name='auth.forgot'),
|
||||
url(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'),
|
||||
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'),
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import (
|
||||
authenticate, login as auth_login, logout as auth_logout,
|
||||
)
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from pretix.base.forms.auth import LoginForm, RegistrationForm
|
||||
from pretix.base.forms.auth import (
|
||||
LoginForm, PasswordForgotForm, PasswordRecoverForm, RegistrationForm,
|
||||
)
|
||||
from pretix.base.models import User
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
|
||||
|
||||
def login(request):
|
||||
@@ -15,9 +24,7 @@ def login(request):
|
||||
"""
|
||||
ctx = {}
|
||||
if request.user.is_authenticated():
|
||||
if "next" in request.GET:
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
return redirect('control:index')
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
if request.method == 'POST':
|
||||
form = LoginForm(data=request.POST)
|
||||
if form.is_valid() and form.user_cache:
|
||||
@@ -45,9 +52,7 @@ def register(request):
|
||||
"""
|
||||
ctx = {}
|
||||
if request.user.is_authenticated():
|
||||
if "next" in request.GET:
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
return redirect('control:index')
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
if request.method == 'POST':
|
||||
form = RegistrationForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
@@ -63,3 +68,88 @@ def register(request):
|
||||
form = RegistrationForm()
|
||||
ctx['form'] = form
|
||||
return render(request, 'pretixcontrol/auth/register.html', ctx)
|
||||
|
||||
|
||||
class Forgot(TemplateView):
|
||||
template_name = 'pretixcontrol/auth/forgot.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated():
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if self.form.is_valid():
|
||||
user = self.form.cleaned_data['user']
|
||||
mail(
|
||||
user.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt',
|
||||
{
|
||||
'user': user,
|
||||
'url': (build_absolute_uri('control:auth.forgot.recover')
|
||||
+ '?id=%d&token=%s' % (user.id, default_token_generator.make_token(user)))
|
||||
},
|
||||
None, locale=user.locale
|
||||
)
|
||||
messages.success(request, _('We sent you an e-mail containing further instructions.'))
|
||||
return redirect('control:auth.forgot')
|
||||
else:
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
@cached_property
|
||||
def form(self):
|
||||
return PasswordForgotForm(data=self.request.POST if self.request.method == 'POST' else None)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['form'] = self.form
|
||||
return context
|
||||
|
||||
|
||||
class Recover(TemplateView):
|
||||
template_name = 'pretixcontrol/auth/recover.html'
|
||||
|
||||
error_messages = {
|
||||
'invalid': _('You clicked on an invalid link. Please check that you copied the full '
|
||||
'web address into your address bar. Please note that the link is only valid '
|
||||
'for three days and that the link can only be used once.'),
|
||||
'unknownuser': _('We were unable to find the user you requested a new password for.')
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated():
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
try:
|
||||
user = User.objects.get(id=self.request.GET.get('id'))
|
||||
except User.DoesNotExist:
|
||||
return self.invalid('unknownuser')
|
||||
if not default_token_generator.check_token(user, self.request.GET.get('token')):
|
||||
return self.invalid('invalid')
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def invalid(self, msg):
|
||||
messages.error(self.request, self.error_messages[msg])
|
||||
return redirect('control:auth.forgot')
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if self.form.is_valid():
|
||||
try:
|
||||
user = User.objects.get(id=self.request.GET.get('id'))
|
||||
except User.DoesNotExist:
|
||||
return self.invalid('unknownuser')
|
||||
if not default_token_generator.check_token(user, self.request.GET.get('token')):
|
||||
return self.invalid('invalid')
|
||||
user.set_password(self.form.cleaned_data['password'])
|
||||
user.save()
|
||||
messages.success(request, _('You can now login using your new password.'))
|
||||
return redirect('control:auth.login')
|
||||
else:
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
@cached_property
|
||||
def form(self):
|
||||
return PasswordRecoverForm(data=self.request.POST if self.request.method == 'POST' else None)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['form'] = self.form
|
||||
return context
|
||||
|
||||
Reference in New Issue
Block a user