You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
16 KiB
388 lines
16 KiB
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordResetForm
|
|
from django import forms
|
|
from .models import CustomUser
|
|
import re # Import the re module for regular expressions
|
|
from .utils.licence_validator import LicenseValidator
|
|
from django.core.mail import send_mail
|
|
from django.template.loader import render_to_string
|
|
from django.utils.http import urlsafe_base64_encode
|
|
from django.contrib.auth.tokens import default_token_generator
|
|
from django.contrib.sites.shortcuts import get_current_site
|
|
from django.utils.encoding import force_bytes
|
|
from django.contrib.auth.forms import PasswordChangeForm
|
|
from django.contrib.auth.forms import AuthenticationForm
|
|
from django.contrib.auth import authenticate # Add this import
|
|
import logging
|
|
|
|
class CustomUserCreationForm(UserCreationForm):
|
|
usable_password = None
|
|
def clean_licence_id(self):
|
|
licence_id = self.cleaned_data.get('licence_id')
|
|
if licence_id:
|
|
licence_id = licence_id.replace(' ', '').strip().upper()
|
|
validator = LicenseValidator(licence_id)
|
|
if validator.validate_license():
|
|
licence_id = validator.computed_licence_id
|
|
else:
|
|
raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
|
|
return licence_id
|
|
|
|
def clean_email(self):
|
|
email = self.cleaned_data.get('email')
|
|
if email:
|
|
email = email.lower()
|
|
if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return email
|
|
|
|
def clean_username(self):
|
|
username = self.cleaned_data.get('username')
|
|
if username:
|
|
username = username.lower()
|
|
if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return username
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
error_messages = {
|
|
'email': {
|
|
'unique': "Cette adresse email est déjà utilisée.",
|
|
},
|
|
'username': {
|
|
'unique': "Ce nom d'utilisateur est déjà pris.",
|
|
},
|
|
'licence_id': {
|
|
'unique': "Cette licence est déjà utilisée par un autre compte.",
|
|
},
|
|
|
|
}
|
|
|
|
fields = UserCreationForm.Meta.fields + ('umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id', 'country')
|
|
|
|
class SimpleCustomUserCreationForm(UserCreationForm):
|
|
usable_password = None
|
|
|
|
def clean_licence_id(self):
|
|
licence_id = self.cleaned_data.get('licence_id')
|
|
if licence_id:
|
|
licence_id = licence_id.replace(' ', '').strip().upper()
|
|
validator = LicenseValidator(licence_id)
|
|
if validator.validate_license():
|
|
licence_id = validator.computed_licence_id
|
|
else:
|
|
raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
|
|
return licence_id
|
|
|
|
def clean_phone(self):
|
|
phone = self.cleaned_data.get('phone')
|
|
if phone:
|
|
# Remove all spaces, dots, dashes, and parentheses
|
|
phone = re.sub(r'[\s\.\-\(\)]', '', phone)
|
|
# Basic regex for phone numbers, allowing 6-15 digits for international numbers
|
|
if not re.match(r"^\+?\d{6,15}$", phone):
|
|
raise forms.ValidationError("Entrer un numéro de téléphone valide.")
|
|
return phone
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = UserCreationForm.Meta.fields + ('email', 'phone', 'first_name', 'last_name', 'licence_id', 'country')
|
|
error_messages = {
|
|
'email': {
|
|
'unique': "Cette adresse email est déjà utilisée.",
|
|
},
|
|
'username': {
|
|
'unique': "Ce nom d'utilisateur est déjà pris.",
|
|
},
|
|
'licence_id': {
|
|
'unique': "Cette licence est déjà utilisée par un autre compte.",
|
|
},
|
|
|
|
}
|
|
labels = {
|
|
'username': 'Nom d’utilisateur',
|
|
'email': 'E-mail',
|
|
'phone': 'Numéro de téléphone',
|
|
'first_name': 'Prénom',
|
|
'last_name': 'Nom de famille',
|
|
'licence_id': 'Numéro de licence',
|
|
'country': 'Pays',
|
|
'password1': 'Mot de passe',
|
|
'password2': 'Confirmer le mot de passe',
|
|
}
|
|
|
|
def clean_email(self):
|
|
email = self.cleaned_data.get('email')
|
|
if email:
|
|
email = email.lower()
|
|
if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return email
|
|
|
|
def clean_username(self):
|
|
username = self.cleaned_data.get('username')
|
|
if username:
|
|
username = username.lower()
|
|
if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return username
|
|
|
|
|
|
class CustomUserChangeForm(UserChangeForm):
|
|
def clean_username(self):
|
|
username = self.cleaned_data.get('username')
|
|
if username:
|
|
username = username.lower()
|
|
if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return username
|
|
|
|
def clean_licence_id(self):
|
|
licence_id = self.cleaned_data.get('licence_id')
|
|
if licence_id:
|
|
licence_id = licence_id.replace(' ', '').strip().upper()
|
|
validator = LicenseValidator(licence_id)
|
|
if validator.validate_license():
|
|
licence_id = validator.computed_licence_id
|
|
else:
|
|
raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
|
|
return licence_id
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
error_messages = {
|
|
'email': {
|
|
'unique': "Cette adresse email est déjà utilisée.",
|
|
},
|
|
'username': {
|
|
'unique': "Ce nom d'utilisateur est déjà pris.",
|
|
},
|
|
'licence_id': {
|
|
'unique': "Cette licence est déjà utilisée par un autre compte.",
|
|
},
|
|
|
|
}
|
|
fields = UserCreationForm.Meta.fields + ('umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id', 'country')
|
|
|
|
class SimpleForm(forms.Form):
|
|
# A single field for user input (e.g., a text field)
|
|
name = forms.CharField(label='Enter your name!', max_length=100)
|
|
|
|
class TournamentRegistrationForm(forms.Form):
|
|
#first_name = forms.CharField(label='Prénom', max_length=50)
|
|
#last_name = forms.CharField(label='Nom', max_length=50)
|
|
email = forms.EmailField(label='E-mail')
|
|
mobile_number = forms.CharField(
|
|
label='Téléphone',
|
|
max_length=15,
|
|
required=True
|
|
)
|
|
|
|
def clean_mobile_number(self):
|
|
mobile_number = self.cleaned_data.get('mobile_number')
|
|
if mobile_number:
|
|
# Remove spaces, dots, dashes, and parentheses from the number first
|
|
mobile_number = re.sub(r'[\s\.\-\(\)]', '', mobile_number)
|
|
if not re.match(r"^\+?\d{6,15}$", mobile_number):
|
|
raise forms.ValidationError("Entrer un numéro de téléphone valide.")
|
|
return mobile_number
|
|
|
|
class AddPlayerForm(forms.Form):
|
|
licence_id = forms.CharField(label='Numéro de licence (avec la lettre)', max_length=20, required=False)
|
|
first_name = forms.CharField(label='Prénom', min_length=2, max_length=50, required=False)
|
|
last_name = forms.CharField(label='Nom', min_length=2, max_length=50, required=False)
|
|
first_tournament = False
|
|
user_without_licence = False
|
|
|
|
def names_is_valid(self):
|
|
first_name = self.cleaned_data.get('first_name')
|
|
last_name = self.cleaned_data.get('last_name')
|
|
return len(first_name) >= 2 and len(last_name) >= 2
|
|
|
|
def clean_licence_id(self):
|
|
licence_id = self.cleaned_data.get('licence_id')
|
|
if licence_id:
|
|
licence_id = licence_id.replace(' ', '').strip().upper()
|
|
return licence_id
|
|
|
|
def clean_last_name(self):
|
|
last_name = self.cleaned_data.get('last_name')
|
|
|
|
# Convert to uppercase
|
|
last_name = last_name.upper()
|
|
|
|
# Update the cleaned_data with the modified licence_id
|
|
self.cleaned_data['last_name'] = last_name
|
|
return last_name
|
|
|
|
def clean_first_name(self):
|
|
first_name = self.cleaned_data.get('first_name')
|
|
|
|
# Convert to capitalize
|
|
first_name = first_name.capitalize()
|
|
|
|
# Update the cleaned_data with the modified licence_id
|
|
self.cleaned_data['first_name'] = first_name
|
|
return first_name
|
|
|
|
class CustomPasswordResetForm(PasswordResetForm):
|
|
def save(self, *args, **kwargs):
|
|
"""
|
|
Override the save method to send a custom email.
|
|
"""
|
|
email = self.cleaned_data["email"]
|
|
users = self.get_users(email)
|
|
|
|
for user in users:
|
|
# Generate the token for password reset
|
|
token = default_token_generator.make_token(user)
|
|
uid = urlsafe_base64_encode(force_bytes(user.pk))
|
|
|
|
# Prepare the context for the email template
|
|
context = {
|
|
"email": user.email,
|
|
"domain": get_current_site(self.request).domain,
|
|
"site_name": "Padel Club",
|
|
"uid": uid,
|
|
"token": token,
|
|
"protocol": "http", # Use 'https' in production
|
|
}
|
|
|
|
# Render the email content from the template
|
|
subject = "Réinitialisation du mot de passe"
|
|
message = render_to_string("registration/password_reset_email.html", context)
|
|
|
|
# Send the email
|
|
send_mail(subject, message, None, [user.email])
|
|
|
|
class ProfileUpdateForm(forms.ModelForm):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
# Remove autofocus from the 'username' field
|
|
self.fields['username'].widget.attrs.pop("autofocus", None)
|
|
|
|
def clean_email(self):
|
|
email = self.cleaned_data.get('email')
|
|
if email:
|
|
email = email.lower()
|
|
if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return email
|
|
|
|
def clean_username(self):
|
|
username = self.cleaned_data.get('username')
|
|
if username:
|
|
username = username.lower()
|
|
if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
|
|
raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
|
|
return username
|
|
|
|
def clean_licence_id(self):
|
|
licence_id = self.cleaned_data.get('licence_id')
|
|
if licence_id:
|
|
licence_id = licence_id.replace(' ', '').strip().upper()
|
|
validator = LicenseValidator(licence_id)
|
|
if validator.validate_license():
|
|
licence_id = validator.computed_licence_id
|
|
else:
|
|
raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
|
|
return licence_id
|
|
|
|
def clean_phone(self):
|
|
phone = self.cleaned_data.get('phone')
|
|
if phone:
|
|
# Remove all spaces, dots, dashes, and parentheses
|
|
phone = re.sub(r'[\s\.\-\(\)]', '', phone)
|
|
# Basic regex for phone numbers, allowing 6-15 digits for international numbers
|
|
if not re.match(r"^\+?\d{6,15}$", phone):
|
|
raise forms.ValidationError("Entrer un numéro de téléphone valide.")
|
|
return phone
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ['first_name', 'last_name', 'licence_id', 'username', 'email', 'phone']
|
|
labels = {
|
|
'username': 'Nom d’utilisateur',
|
|
'email': 'E-mail',
|
|
'phone': 'Numéro de téléphone',
|
|
'first_name': 'Prénom',
|
|
'last_name': 'Nom de famille',
|
|
'licence_id': 'Numéro de licence',
|
|
}
|
|
error_messages = {
|
|
'email': {
|
|
'unique': "Cette adresse email est déjà utilisée.",
|
|
},
|
|
'username': {
|
|
'unique': "Ce nom d'utilisateur est déjà pris.",
|
|
},
|
|
'licence_id': {
|
|
'unique': "Cette licence est déjà utilisée par un autre compte.",
|
|
},
|
|
}
|
|
|
|
class CustomPasswordChangeForm(PasswordChangeForm):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
# Remove autofocus from all fields in the PasswordChangeForm
|
|
for field in self.fields.values():
|
|
field.widget.attrs.pop("autofocus", None)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class EmailOrUsernameAuthenticationForm(AuthenticationForm):
|
|
username = forms.CharField(label='Username or Email')
|
|
|
|
def clean(self):
|
|
username = self.cleaned_data.get('username')
|
|
password = self.cleaned_data.get('password')
|
|
|
|
logger.info(f"Login attempt with username/email: {username}")
|
|
|
|
if username and password:
|
|
# Check if user exists first (either by username or email)
|
|
user_exists = None
|
|
try:
|
|
# Try to find user by username first
|
|
user_exists = CustomUser.objects.get(username__iexact=username)
|
|
except CustomUser.DoesNotExist:
|
|
# Try to find user by email
|
|
try:
|
|
user_exists = CustomUser.objects.get(email__iexact=username)
|
|
except CustomUser.DoesNotExist:
|
|
pass
|
|
|
|
# If user exists but is inactive, provide specific feedback
|
|
if user_exists and not user_exists.is_active:
|
|
# Store the inactive user in session for template use
|
|
if hasattr(self, 'request') and self.request.session:
|
|
self.request.session['inactive_user_email'] = user_exists.email
|
|
self.request.session['inactive_user_id'] = str(user_exists.id)
|
|
|
|
raise forms.ValidationError(
|
|
"Votre compte n'est pas encore activé. Veuillez cliquer sur le lien d'activation envoyé à votre adresse e-mail.",
|
|
code='inactive_account'
|
|
)
|
|
|
|
# Try regular authentication
|
|
self.user_cache = authenticate(
|
|
self.request,
|
|
username=username,
|
|
password=password
|
|
)
|
|
|
|
if self.user_cache is None:
|
|
logger.warning("Authentication failed")
|
|
raise forms.ValidationError(
|
|
"Identifiant/E-mail ou mot de passe incorrect. Les champs sont sensibles à la casse.",
|
|
code='invalid_login'
|
|
)
|
|
else:
|
|
logger.info(f"Authentication successful for user: {self.user_cache}")
|
|
# Clear any inactive user session data on successful login
|
|
if hasattr(self, 'request') and self.request.session:
|
|
self.request.session.pop('inactive_user_email', None)
|
|
self.request.session.pop('inactive_user_id', None)
|
|
self.confirm_login_allowed(self.user_cache)
|
|
|
|
return self.cleaned_data
|
|
|