diff --git a/accounts/admin.py b/accounts/admin.py index 40728fadf5875bb9c9b564aaf2b90d328e9d2a9a..f9e5b896b7cd167a3c749db8801a4201b393b6e6 100644 --- a/accounts/admin.py +++ b/accounts/admin.py @@ -9,9 +9,9 @@ admin.site.unregister(Group) @admin.register(EmailUser) class EmailUserAdmin(admin.ModelAdmin): """option d'affichage des activités dans la vue django admin""" - list_display = ("email", "last_name", "first_name", "is_superuser") - list_filter = ("is_superuser",) - list_editable = ("is_superuser",) + list_display = ("email", "last_name", "first_name", "is_superuser", "is_active", "email_confirmed",) + list_filter = ("is_superuser","is_active", "email_confirmed",) + list_editable = ("is_superuser","is_active") fields = ("email", "last_name", "first_name", "is_superuser", ("date_joined", "last_login",), ) diff --git a/accounts/models.py b/accounts/models.py index bd52c6fbb1b1023543291666eeaa07437c77a3e9..36bda398ee08586409d86575bc006a788b73bb55 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -34,6 +34,7 @@ class EmailUser(AbstractUser): email = models.EmailField('adresse email', unique=True) first_name = models.CharField('prénom', max_length=100) last_name = models.CharField("nom", max_length=100) + email_confirmed = models.BooleanField("Email vérifié", default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ("last_name", "first_name",) diff --git a/accounts/urls.py b/accounts/urls.py index 7abee4309f15de3b774f80d2bd8538e85c0e588d..47d47d739dc31d02ce28559e8c342ebd928f2148 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -1,12 +1,13 @@ from django.urls import include, path import django.contrib.auth.views as dj_auth_views -from accounts.views import create_account, logout_view +from accounts.views import logout_view, ActivateAccountView, CreateAccountView app_name = "accounts" urlpatterns = [ path("login/", dj_auth_views.LoginView.as_view(), name="login"), path("logout/", logout_view, name="logout"), - path("create/", create_account, name="create") + path("create/", CreateAccountView.as_view(), name="create"), + path('activate/<uidb64>/<token>/', ActivateAccountView.as_view(), name='activate'), ] diff --git a/accounts/views.py b/accounts/views.py index db899e4cf2eddc422c85ee989d578d8a154b5bd4..1698d132070891ecd18e36272e82bb4ba966d675 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,10 +1,20 @@ from django.conf import settings +from django.contrib import messages from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site from django.http import Http404 +from django.utils.encoding import force_bytes, force_text +from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode +from django.urls import reverse +from django.template.loader import render_to_string +from django.views.generic import RedirectView, View from django.shortcuts import render, redirect from accounts.forms import CreateAccountForm +from accounts.models import EmailUser +from accounts.tokens import email_token_generator +from site_settings.models import SiteSettings @login_required def logout_view(request): @@ -12,25 +22,78 @@ def logout_view(request): logout(request) return redirect("home") -def create_account(request): - """Vue pour l'inscription""" - if not settings.REGISTRATION_USER_CREATION_OPEN: - raise Http404("La création de compte n'est pas ouverte actuellement") - if request.method == 'POST': - form = CreateAccountForm(request.POST) - if form.is_valid(): - user = form.save() - user.refresh_from_db() - # load the profile instance created by the signal - user.save() - raw_password = form.cleaned_data.get('password1') - - # login user after signing up - user = authenticate(email=user.email, password=raw_password) - login(request, user) - - # redirect user to home page - return redirect('home') - else: - form = CreateAccountForm() - return render(request, 'registration/create_account.html', {'form': form}) +class CreateAccountView(View): + """Vue pour la creation de compte""" + form_class = CreateAccountForm + template_name = 'registration/create_account.html' + + @staticmethod + def check_creation_allowed(): + """Vérifie que la création de compte est authorisée + Renvoie un 404 si ce n'est pas le cas""" + settings = SiteSettings.load() + if not settings.registrations_open: + raise Http404("La création de compte n'est pas ouverte actuellement") + + def get(self, request, *args, **kwargs): + """handle get requests""" + self.check_creation_allowed() + form = self.form_class() + return render(request, self.template_name, {'form': form}) + + def post(self, request, *args, **kwargs): + """handle post requests""" + self.check_creation_allowed() + form = self.form_class(request.POST) + if not form.is_valid(): + return render(request, self.template_name, {'form': form}) + + user = form.save() + user.is_active = False # can't login until email validation + user.email_confirmed = False + + current_site = get_current_site(request) + subject = 'Activation de votre compte Interludes' + message = render_to_string('registration/activation_email.html', { + 'user': user, + 'domain': current_site.domain, + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'token': email_token_generator.make_token(user), + }) + user.email_user(subject, message) + + user.save() + + messages.success(request, ('Please Confirm your email to complete registration.')) + + return redirect('accounts:login') + +class ActivateAccountView(RedirectView): + + permanent = False + + def get_redirect_url(self, uidb64, token, *args, **kwargs): + try: + uid = urlsafe_base64_decode(uidb64).decode() + user = EmailUser.objects.get(pk=uid) + except (TypeError, ValueError, OverflowError, EmailUser.DoesNotExist): + messages.error( + self.request, + "Le lien de confirmation d'adresse mail ne correspond à aucun·e " + "utilisateur·ice inscrit·e", + ) + return reverse("home") + + if not email_token_generator.check_token(user, token): + messages.error( + self.request, + "Le lien de confirmation d'adresse mail est invalide ou déjà utilisé", + ) + return reverse("home") + + user.is_active = True + user.email_confirmed = True + user.save() + login(self.request, user) + messages.info(self.request, "Votre adresse email a bien été confirmée.") + return reverse("home") diff --git a/home/templates/base.html b/home/templates/base.html index 4252d790ff7aa90d105968b808d4031f73906400..7ffb9a4a135ca7afaf7a54eccd2ea6694707140e 100644 --- a/home/templates/base.html +++ b/home/templates/base.html @@ -62,6 +62,14 @@ </nav> <main> + {% if messages %} + <ul class="messages"> + {% for message in messages %} + <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> + {% endfor %} + </ul> + {% endif %} + {% block "content" %} {% endblock %} </main> diff --git a/interludes/settings.py b/interludes/settings.py index 03b41d8daad925207b232fb7d6e9058dc4062427..b36a61da2c4789af0b661426de616564921ff7e3 100644 --- a/interludes/settings.py +++ b/interludes/settings.py @@ -25,6 +25,8 @@ SECRET_KEY = 'tx$xi%n!8cghirp377zb)gd24g#=&w*ik(bx2h(i8ji0_&9_5l' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +ADMINS = [("respos", "respointerludes2021@ens.psl.eu"),] + ALLOWED_HOSTS = [] @@ -136,3 +138,7 @@ LOGIN_REDIRECT_URL = 'home' REGISTRATION_USER_CREATION_OPEN = True # Blocks event inscription REGISTRATION_EVENT_INSCRIPTIONS_OPEN = True + + +# This will display email in Console. +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'