mirror of
https://gitlab.com/animath/si/plateforme-corres2math.git
synced 2025-06-21 18:38:24 +02:00
Confirm email addresses
This commit is contained in:
@ -6,6 +6,7 @@ class RegistrationConfig(AppConfig):
|
||||
name = 'registration'
|
||||
|
||||
def ready(self):
|
||||
from registration.signals import set_username, create_admin_registration
|
||||
from registration.signals import set_username, send_email_link, create_admin_registration
|
||||
pre_save.connect(set_username, "auth.User")
|
||||
pre_save.connect(send_email_link, "auth.User")
|
||||
post_save.connect(create_admin_registration, "auth.User")
|
||||
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-22 16:56
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('registration', '0002_auto_20200921_1948'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='registration',
|
||||
name='email_confirmed',
|
||||
field=models.BooleanField(default=False, verbose_name='email confirmed'),
|
||||
),
|
||||
]
|
@ -1,7 +1,13 @@
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
from django.template import loader
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
from corres2math.tokens import email_validation_token
|
||||
|
||||
|
||||
class Registration(PolymorphicModel):
|
||||
user = models.OneToOneField(
|
||||
@ -15,6 +21,36 @@ class Registration(PolymorphicModel):
|
||||
verbose_name=_("Grant Animath to contact me in the future about other actions"),
|
||||
)
|
||||
|
||||
email_confirmed = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("email confirmed"),
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.send_email_validation_link()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
def send_email_validation_link(self):
|
||||
subject = "[Corres2math] " + str(_("Activate your Correspondances account"))
|
||||
token = email_validation_token.make_token(self.user)
|
||||
uid = urlsafe_base64_encode(force_bytes(self.user.pk))
|
||||
site = Site.objects.first()
|
||||
message = loader.render_to_string('registration/mails/email_validation_email.txt',
|
||||
{
|
||||
'user': self.user,
|
||||
'domain': site.domain,
|
||||
'token': token,
|
||||
'uid': uid,
|
||||
})
|
||||
html = loader.render_to_string('registration/mails/email_validation_email.html',
|
||||
{
|
||||
'user': self.user,
|
||||
'domain': site.domain,
|
||||
'token': token,
|
||||
'uid': uid,
|
||||
})
|
||||
self.user.email_user(subject, message, html_message=html)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
raise NotImplementedError
|
||||
|
@ -1,10 +1,23 @@
|
||||
from registration.models import AdminRegistration
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from registration.models import AdminRegistration, Registration
|
||||
|
||||
|
||||
def set_username(instance, **_):
|
||||
instance.username = instance.email
|
||||
|
||||
|
||||
def send_email_link(instance, **_):
|
||||
if instance.pk:
|
||||
old_instance = User.objects.get(pk=instance.pk)
|
||||
if old_instance.email != instance.email:
|
||||
registration = Registration.objects.get(user=instance)
|
||||
registration.email_confirmed = False
|
||||
registration.save()
|
||||
registration.user = instance
|
||||
registration.send_email_validation_link()
|
||||
|
||||
|
||||
def create_admin_registration(instance, **_):
|
||||
if instance.is_superuser:
|
||||
AdminRegistration.objects.get_or_create(user=instance)
|
||||
|
@ -1,9 +1,13 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import SignupView
|
||||
from .views import SignupView, UserValidationEmailSentView, UserResendValidationEmailView, UserValidateView
|
||||
|
||||
app_name = "registration"
|
||||
|
||||
urlpatterns = [
|
||||
path("signup", SignupView.as_view(), name="signup"),
|
||||
path('validate_email/sent/', UserValidationEmailSentView.as_view(), name='email_validation_sent'),
|
||||
path('validate_email/resend/<int:pk>/', UserResendValidationEmailView.as_view(),
|
||||
name='email_validation_resend'),
|
||||
path('validate_email/<uidb64>/<token>/', UserValidateView.as_view(), name='email_validation'),
|
||||
]
|
||||
|
@ -1,8 +1,15 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.shortcuts import resolve_url, redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import CreateView
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, TemplateView, DetailView
|
||||
|
||||
from corres2math.tokens import email_validation_token
|
||||
from .forms import SignupForm, StudentRegistrationForm, CoachRegistrationForm
|
||||
|
||||
|
||||
@ -39,3 +46,78 @@ class SignupView(CreateView):
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("index")
|
||||
|
||||
|
||||
class UserValidateView(TemplateView):
|
||||
"""
|
||||
A view to validate the email address.
|
||||
"""
|
||||
title = _("Email validation")
|
||||
template_name = 'registration/email_validation_complete.html'
|
||||
extra_context = {"title": _("Validate email")}
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""
|
||||
With a given token and user id (in params), validate the email address.
|
||||
"""
|
||||
assert 'uidb64' in kwargs and 'token' in kwargs
|
||||
|
||||
self.validlink = False
|
||||
user = self.get_user(kwargs['uidb64'])
|
||||
token = kwargs['token']
|
||||
|
||||
# Validate the token
|
||||
if user is not None and email_validation_token.check_token(user, token):
|
||||
self.validlink = True
|
||||
user.registration.email_confirmed = True
|
||||
user.save()
|
||||
return self.render_to_response(self.get_context_data(), status=200 if self.validlink else 400)
|
||||
|
||||
def get_user(self, uidb64):
|
||||
"""
|
||||
Get user from the base64-encoded string.
|
||||
"""
|
||||
try:
|
||||
# urlsafe_base64_decode() decodes to bytestring
|
||||
uid = urlsafe_base64_decode(uidb64).decode()
|
||||
user = User.objects.get(pk=uid)
|
||||
except (TypeError, ValueError, OverflowError, User.DoesNotExist, ValidationError):
|
||||
user = None
|
||||
return user
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['user_object'] = self.get_user(self.kwargs["uidb64"])
|
||||
context['login_url'] = resolve_url(settings.LOGIN_URL)
|
||||
if self.validlink:
|
||||
context['validlink'] = True
|
||||
else:
|
||||
context.update({
|
||||
'title': _('Email validation unsuccessful'),
|
||||
'validlink': False,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class UserValidationEmailSentView(TemplateView):
|
||||
"""
|
||||
Display the information that the validation link has been sent.
|
||||
"""
|
||||
template_name = 'registration/email_validation_email_sent.html'
|
||||
extra_context = {"title": _('Email validation email sent')}
|
||||
|
||||
|
||||
class UserResendValidationEmailView(LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
Rensend the email validation link.
|
||||
"""
|
||||
model = User
|
||||
extra_context = {"title": _("Resend email validation link")}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user = self.get_object()
|
||||
|
||||
user.profile.send_email_validation_link()
|
||||
|
||||
# TODO Change URL
|
||||
return redirect('index')
|
||||
|
Reference in New Issue
Block a user