Ajout de la gestion de l'activation des comptes utilisateur par e-mail, des validations pour les pseudos existants, et configuration par défaut de l'e-mail backend.

This commit is contained in:
mrtoine 2025-12-16 10:19:47 +01:00
parent ca0211e841
commit fc4939577a
5 changed files with 74 additions and 4 deletions

View file

@ -202,4 +202,7 @@ def get_git_version():
else: else:
return "Version inconnue (Fichier manquant)" return "Version inconnue (Fichier manquant)"
GIT_VERSION = get_git_version() GIT_VERSION = get_git_version()
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DEFAULT_FROM_EMAIL = 'noreply@partirdezero.local'

View file

@ -27,7 +27,15 @@ class UserRegistrationForm(forms.Form):
password2 = cleaned_data.get("password2") password2 = cleaned_data.get("password2")
if password1 and password2 and password1 != password2: if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords do not match") raise forms.ValidationError("Les mots de passe ne correspondent pas.")
return cleaned_data
def clean_username(self):
username = self.cleaned_data.get('username')
if username and User.objects.filter(username__iexact=username).exists():
raise forms.ValidationError("Ce pseudo est déjà pris. Veuillez en choisir un autre.")
return username
class UserLoginForm(forms.Form): class UserLoginForm(forms.Form):
username = forms.CharField( username = forms.CharField(

4
users/tokens.py Normal file
View file

@ -0,0 +1,4 @@
from django.contrib.auth.tokens import PasswordResetTokenGenerator
# Générateur de tokens pour l'activation de compte
activation_token = PasswordResetTokenGenerator()

View file

@ -7,6 +7,8 @@ urlpatterns = [
path('', views.register, name='register'), path('', views.register, name='register'),
path('login/', views.login, name='login'), path('login/', views.login, name='login'),
path('logout/', views.logout, name='logout'), path('logout/', views.logout, name='logout'),
# Activation de compte par lien tokenisé
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
path('profile/view/<int:user_id>/', views.another_profile, name='another_profile'), path('profile/view/<int:user_id>/', views.another_profile, name='another_profile'),
path('complete-profile/', views.complete_profile, name='complete_profile'), path('complete-profile/', views.complete_profile, name='complete_profile'),
path('profile/', views.profile, name='profile'), path('profile/', views.profile, name='profile'),

View file

@ -5,6 +5,11 @@ from django.contrib.auth.models import User
from courses.models import Course from courses.models import Course
from .forms import UserRegistrationForm, UserLoginForm, UserUpdateForm, ProfileUpdateForm, CompleteProfileForm from .forms import UserRegistrationForm, UserLoginForm, UserUpdateForm, ProfileUpdateForm, CompleteProfileForm
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.urls import reverse
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from .tokens import activation_token
def register(request): def register(request):
# Si l'utilisateur est deja connecté, on le redirige vers la page de profil # Si l'utilisateur est deja connecté, on le redirige vers la page de profil
@ -13,13 +18,36 @@ def register(request):
if request.method == 'POST': if request.method == 'POST':
form = UserRegistrationForm(request.POST) form = UserRegistrationForm(request.POST)
if form.is_valid(): if form.is_valid():
# Crée un utilisateur inactif en attente d'activation par email
user = User.objects.create_user( user = User.objects.create_user(
username=form.cleaned_data['username'], username=form.cleaned_data['username'],
email=form.cleaned_data['email'], email=form.cleaned_data['email'],
password=form.cleaned_data['password1'] password=form.cleaned_data['password1']
) )
auth_login(request, user) user.is_active = False
return redirect('profile') user.save()
# Envoi du lien d'activation par email
uid = urlsafe_base64_encode(force_bytes(user.pk))
token = activation_token.make_token(user)
activation_link = request.build_absolute_uri(
reverse('activate', kwargs={'uidb64': uid, 'token': token})
)
subject = 'Active ton compte sur partirdezero'
message = (
'Bienvenue !\n\n'
'Pour activer ton compte, clique sur le lien suivant (valide pendant une durée limitée) :\n'
f'{activation_link}\n\n'
"Si tu n'es pas à l'origine de cette inscription, ignore ce message."
)
try:
send_mail(subject, message, None, [user.email], fail_silently=True)
except Exception:
# Même si l'envoi échoue, on n'interrompt pas le flux; un admin vérifiera la config email
pass
messages.success(request, "Inscription réussie. Vérifie ta boîte mail pour activer ton compte.")
return redirect('login')
else: else:
form = UserRegistrationForm() form = UserRegistrationForm()
return render(request, 'users/register.html', {'form': form}) return render(request, 'users/register.html', {'form': form})
@ -32,8 +60,15 @@ def login(request):
password = form.cleaned_data['password'] password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password) user = authenticate(request, username=username, password=password)
if user is not None: if user is not None:
if not user.is_active:
messages.error(request, "Votre compte n'est pas encore activé. Consultez l'email d'activation envoyé." )
return render(request, 'users/login.html', {'form': form})
auth_login(request, user) auth_login(request, user)
return redirect('profile') return redirect('profile')
else:
# Identifiants invalides: avertir l'utilisateur
messages.error(request, "Nom d'utilisateur ou mot de passe incorrect.")
return render(request, 'users/login.html', {'form': form})
else: else:
form = UserLoginForm() form = UserLoginForm()
return render(request, 'users/login.html', {'form': form}) return render(request, 'users/login.html', {'form': form})
@ -106,3 +141,21 @@ def create_post(request):
def another_profile(request, user_id): def another_profile(request, user_id):
user = User.objects.get(id=user_id) user = User.objects.get(id=user_id)
return render(request, 'users/another_profile.html', {'user': user}) return render(request, 'users/another_profile.html', {'user': user})
# Activation de compte via lien tokenisé
def activate(request, uidb64, token):
try:
uid = urlsafe_base64_decode(uidb64).decode()
user = User.objects.get(pk=uid)
except Exception:
user = None
if user and activation_token.check_token(user, token):
if not user.is_active:
user.is_active = True
user.save()
messages.success(request, 'Votre compte a été activé. Vous pouvez maintenant vous connecter.')
return redirect('login')
messages.error(request, "Lien d'activation invalide ou expiré. Demandez un nouveau lien ou inscrivezvous à nouveau.")
return redirect('register')