From 9c456a9357af27a558d802f910d76f015505716f Mon Sep 17 00:00:00 2001 From: Raz Date: Sat, 29 Mar 2025 20:18:56 +0100 Subject: [PATCH] fix lot of stuff around forms and password reset --- tournaments/custom_views.py | 20 +++++-- .../services/tournament_registration.py | 13 +++++ tournaments/templates/profile.html | 52 +++++++++--------- .../templates/register_tournament.html | 51 ++++++++---------- tournaments/templates/registration/login.html | 8 +-- .../registration/password_reset_complete.html | 4 +- .../registration/password_reset_confirm.html | 18 +------ .../registration/password_reset_done.html | 4 +- .../registration/password_reset_form.html | 17 +----- .../templates/registration/signup.html | 53 ++++++++++--------- .../tournaments/tournament_info.html | 9 ---- tournaments/urls.py | 12 ++--- tournaments/views.py | 53 +++++++++++++++++++ 13 files changed, 178 insertions(+), 136 deletions(-) diff --git a/tournaments/custom_views.py b/tournaments/custom_views.py index 01d54bb..4e3d2f1 100644 --- a/tournaments/custom_views.py +++ b/tournaments/custom_views.py @@ -10,19 +10,33 @@ class CustomLoginView(auth_views.LoginView): def get_success_url(self): # First check the 'next' parameter which has higher priority next_url = self.request.POST.get('next') or self.request.GET.get('next') + + # Check if the next URL is a password reset page and avoid that redirect if next_url and next_url.strip(): + # Avoid redirecting to password reset pages after login + if 'reset' in next_url or 'password_reset' in next_url: + # Redirect to profile or index instead + return reverse('profile') return next_url # Then check if we have a stored referrer URL referrer = self.request.session.get('login_referrer') if referrer: - # Clear the stored referrer to prevent reuse - del self.request.session['login_referrer'] - return referrer + # Avoid redirecting to password reset pages from stored referrer + if 'reset' not in referrer and 'password_reset' not in referrer: + # Clear the stored referrer to prevent reuse + del self.request.session['login_referrer'] + return referrer # Fall back to default return reverse('index') def get(self, request, *args, **kwargs): + # Clear any potential password reset session data + keys_to_clear = [key for key in request.session.keys() + if 'reset' in key or 'password' in key] + for key in keys_to_clear: + del request.session[key] + messages.get_messages(request).used = True return super().get(request, *args, **kwargs) diff --git a/tournaments/services/tournament_registration.py b/tournaments/services/tournament_registration.py index 0233edb..d42ae9e 100644 --- a/tournaments/services/tournament_registration.py +++ b/tournaments/services/tournament_registration.py @@ -48,6 +48,13 @@ class TournamentRegistrationService: if not self.context['add_player_form'].is_valid(): return + # Clear existing messages if the form is valid + from django.contrib.messages import get_messages + storage = get_messages(self.request) + # Iterate through the storage to clear it + for _ in storage: + pass + player_data = self.context['add_player_form'].cleaned_data licence_id = player_data.get('licence_id', '').upper() @@ -112,6 +119,12 @@ class TournamentRegistrationService: self.context['registration_successful'] = True def handle_get_request(self): + from django.contrib.messages import get_messages + storage = get_messages(self.request) + # Iterate through the storage to clear it + for _ in storage: + pass + self.context['add_player_form'] = AddPlayerForm() self.context['team_form'] = self.initialize_team_form() self.initialize_session_data() diff --git a/tournaments/templates/profile.html b/tournaments/templates/profile.html index 9216b92..2e6a1a7 100644 --- a/tournaments/templates/profile.html +++ b/tournaments/templates/profile.html @@ -20,16 +20,34 @@ {% load static %} {% load tz %} +{% if form.errors or password_change_form.errors %} +
+
+
+ {% for field in form %} + {% if field.errors %} + {% for error in field.errors %} +
{{ field.label }} : {{ error }}
+ {% endfor %} + {% endif %} + {% endfor %} +
+
+ {% for field in password_change_form %} + {% if field.errors %} + {% for error in field.errors %} +
{{ field.label }} : {{ error }}
+ {% endfor %} + {% endif %} + {% endfor %} +
+
+
+{% endif %} +
- {% if form.non_field_errors %} -
- {% for error in form.non_field_errors %} -

{{ error }}

- {% endfor %} -
- {% endif %}
{% csrf_token %} {{ form.as_p }} @@ -40,25 +58,7 @@
- {% if password_change_form.errors %} -
- {% for field, errors in password_change_form.errors.items %} - {% for error in errors %} -

{{ error }}

- {% endfor %} - {% endfor %} -
- {% endif %} - - {% if password_change_form.non_field_errors %} -
- {% for error in password_change_form.non_field_errors %} -

{{ error }}

- {% endfor %} -
- {% endif %} - - + {% csrf_token %} {{ password_change_form.as_p }} diff --git a/tournaments/templates/register_tournament.html b/tournaments/templates/register_tournament.html index c8349d1..95a1212 100644 --- a/tournaments/templates/register_tournament.html +++ b/tournaments/templates/register_tournament.html @@ -28,20 +28,27 @@ {% else %} {% if team_form.errors %} -
- {% if team_form.non_field_errors %} - {% for error in team_form.non_field_errors %} -

{{ error }}

- {% endfor %} - {% endif %} - +
{% for field in team_form %} - {% for error in field.errors %} -

{{ error }}

- {% endfor %} + {% if field.errors %} + {% for error in field.errors %} +
{{ field.label }} : {{ error }}
+ {% endfor %} + {% endif %} + {% endfor %} +
+ {% endif %} + + {% if messages %} +
+ {% for message in messages %} +
+ {{ message }} +
{% endfor %}
{% endif %} + {% csrf_token %} @@ -52,6 +59,12 @@ Informations de contact

+ {% if team_form.non_field_errors %} + {% for error in team_form.non_field_errors %} +

{{ error }}

+ {% endfor %} + {% endif %} + {{ team_form.as_p }}
@@ -124,24 +137,6 @@ {% endif %} {% endif %} -
- {% if add_player_form.errors %} -
- {% if add_player_form.non_field_errors %} - {% for error in add_player_form.non_field_errors %} -

{{ error }}

- {% endfor %} - {% endif %} - - {% for field in add_player_form %} - {% for error in field.errors %} -

{{ error }}

- {% endfor %} - {% endfor %} -
- {% endif %} -
- -

+

- {% for message in messages %} -
{{ message }}
- {% endfor %}
{% endblock %} diff --git a/tournaments/templates/registration/password_reset_done.html b/tournaments/templates/registration/password_reset_done.html index bfc7035..28f2b9f 100644 --- a/tournaments/templates/registration/password_reset_done.html +++ b/tournaments/templates/registration/password_reset_done.html @@ -11,9 +11,9 @@ Un e-mail contenant un lien pour réinitialiser votre mot de passe a été envoyé à votre adresse. Veuillez vérifier votre boîte de réception.

-

+

Retour à la connexion -

+
diff --git a/tournaments/templates/registration/password_reset_form.html b/tournaments/templates/registration/password_reset_form.html index 40e8858..cd0e3d7 100644 --- a/tournaments/templates/registration/password_reset_form.html +++ b/tournaments/templates/registration/password_reset_form.html @@ -7,16 +7,6 @@
- {% if form.errors %} -
- {% for field, errors in form.errors.items %} - {% for error in errors %} -

{{ error }}

- {% endfor %} - {% endfor %} -
- {% endif %} - {% if form.non_field_errors %}
@@ -31,13 +21,10 @@ -

+

- {% for message in messages %} -
{{ message }}
- {% endfor %}
{% endblock %} diff --git a/tournaments/templates/registration/signup.html b/tournaments/templates/registration/signup.html index d541d72..26b3b02 100644 --- a/tournaments/templates/registration/signup.html +++ b/tournaments/templates/registration/signup.html @@ -8,35 +8,40 @@ {% load static %} {% load tz %} -
-
-
- {% if form.errors %} -
- {% for field, errors in form.errors.items %} - {% for error in errors %} -

{{ error }}

+
+ {% if form.errors %} +
+
+
+ {% for field in form %} + {% if field.errors %} + {% for error in field.errors %} +
{{ field.label }} : {{ error }}
+ {% endfor %} + {% endif %} {% endfor %} - {% endfor %} +
- {% endif %} +
+ {% endif %} - - {% if form.non_field_errors %} -
- {% for error in form.non_field_errors %} -

{{ error }}

- {% endfor %} -
- {% endif %} +
+
+ {% if form.non_field_errors %} +
+ {% for error in form.non_field_errors %} +

{{ error }}

+ {% endfor %} +
+ {% endif %} -
- {% csrf_token %} - {{ form.as_p }} - -
+
+ {% csrf_token %} + {{ form.as_p }} + +
+
-
{% endblock %} diff --git a/tournaments/templates/tournaments/tournament_info.html b/tournaments/templates/tournaments/tournament_info.html index 9c93a55..822bcee 100644 --- a/tournaments/templates/tournaments/tournament_info.html +++ b/tournaments/templates/tournaments/tournament_info.html @@ -47,12 +47,6 @@ {% if tournament.is_unregistration_possible %}

-

- {% for message in messages %} -
{{ message }}
- {% endfor %} -
- @@ -164,9 +158,6 @@

{% endif %} {% else %} - {% for message in messages %} -
{{ message }}
- {% endfor %}

Connectez-vous ! diff --git a/tournaments/urls.py b/tournaments/urls.py index f544567..e0a49bb 100644 --- a/tournaments/urls.py +++ b/tournaments/urls.py @@ -55,13 +55,7 @@ urlpatterns = [ path('utils/xls-to-csv/', views.xls_to_csv, name='xls-to-csv'), path('mail-test/', views.simple_form_view, name='mail-test'), path('login/', CustomLoginView.as_view(), name='custom-login'), - path('password_change/', - auth_views.PasswordChangeView.as_view( - success_url='/profile/', # Redirect back to profile after success - form_class=CustomPasswordChangeForm - ), - name='password_change' - ), + path('custom_password_change/', views.custom_password_change, name='custom_password_change'), path('logout/', views.custom_logout, name='custom_logout'), path('signup/', views.signup, name='signup'), # URL pattern for signup # path('profile/', views.profile, name='profile'), # URL pattern for signup @@ -70,7 +64,9 @@ urlpatterns = [ path('tournaments//unregister/', views.unregister_tournament, name='unregister_tournament'), path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), path('password_reset_done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'), - path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'), + path('reset/done/', + views.CustomPasswordResetCompleteView.as_view(), + name='password_reset_complete'), path('profile/', views.ProfileUpdateView.as_view(), name='profile'), path('admin/tournament-import/', views.tournament_import_view, name='tournament_import'), path('admin/status/', views.status_page, name='status_page'), diff --git a/tournaments/views.py b/tournaments/views.py index a3dfa5f..14990c6 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -2,6 +2,11 @@ import os import csv +from django.contrib.auth import update_session_auth_hash +from django.contrib.auth.views import PasswordResetCompleteView +from django.shortcuts import redirect +from django.contrib.auth import login +from django.contrib.auth import get_user_model from django.shortcuts import render, get_object_or_404 from django.http import JsonResponse, HttpResponse from django.utils.encoding import force_str @@ -818,6 +823,54 @@ class CustomPasswordResetConfirmView(PasswordResetConfirmView): except (TypeError, ValueError, User.DoesNotExist): raise Http404("User not found") +class CustomPasswordResetCompleteView(PasswordResetCompleteView): + template_name = 'registration/password_reset_complete.html' + + def get(self, request, *args, **kwargs): + # Get the user from the session + username = request.session.get('reset_username') + + if username: + try: + # Get the user + User = get_user_model() + user = User.objects.get(username=username) + + # Log the user in + login(request, user, backend='django.contrib.auth.backends.ModelBackend') + + # Clean up the session + if 'reset_username' in request.session: + del request.session['reset_username'] + + # Redirect to the profile page + return redirect('profile') + except User.DoesNotExist: + pass + + # If no username in session or user not found, proceed with normal view + return super().get(request, *args, **kwargs) + +@login_required +def custom_password_change(request): + if request.method == 'POST': + form = CustomPasswordChangeForm(user=request.user, data=request.POST) + if form.is_valid(): + user = form.save() + update_session_auth_hash(request, user) # Important to keep user logged in + messages.success(request, 'Votre mot de passe a été mis à jour avec succès!') + return redirect('profile') + else: + # Form is invalid, show errors + profile_form = ProfileUpdateForm(instance=request.user) + return render(request, 'profile.html', { + 'form': profile_form, + 'password_change_form': form + }) + + # If not POST, redirect to profile page + return redirect('profile') + @login_required def my_tournaments(request): user = request.user