From 3faf1294d8e27815aefa1b93d9f8c8f1180f6ea9 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 11 Dec 2020 16:09:51 +0100 Subject: [PATCH 01/11] Update import order --- apps/registration/views.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/registration/views.py b/apps/registration/views.py index 6247e09..a0efeeb 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -1,7 +1,5 @@ import os -from django_tables2 import SingleTableView - from corres2math.tokens import email_validation_token from corres2math.views import AdminMixin from django.conf import settings @@ -15,11 +13,12 @@ from django.urls import reverse_lazy from django.utils.http import urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View +from django_tables2 import SingleTableView from magic import Magic from participation.models import Phase from .forms import CoachRegistrationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm -from .models import StudentRegistration, Registration +from .models import Registration, StudentRegistration from .tables import RegistrationTable From f2ca4b74469b8507b1bf32bcde523748a46327a5 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 11 Dec 2020 16:10:05 +0100 Subject: [PATCH 02/11] Update email validation page --- .../email_validation_complete.html | 6 +++++- locale/fr/LC_MESSAGES/django.po | 20 +++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/registration/templates/registration/email_validation_complete.html b/apps/registration/templates/registration/email_validation_complete.html index f58a7e5..4039e0b 100644 --- a/apps/registration/templates/registration/email_validation_complete.html +++ b/apps/registration/templates/registration/email_validation_complete.html @@ -19,7 +19,11 @@ SPDX-License-Identifier: GPL-3.0-or-later

{% else %}

- {% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %} + {% if user.is_authenticated and user.registration.email_confirmed %} + {% trans "The link was invalid. The token may have expired, or your account is already activated. However, your account seems to be already valid." %} + {% else %} + {% trans "The link was invalid. The token may have expired, or your account is already activated. Please send us an email to activate your account." %} + {% endif %}

{% endif %} diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 05dfbc2..a93d97f 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Corres2math\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-11 14:03+0100\n" +"POT-Creation-Date: 2020-12-11 16:09+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -891,13 +891,21 @@ msgstr "Votre email a été validé avec succès." msgid "You can now log in." msgstr "Vous pouvez désormais vous connecter." -#: apps/registration/templates/registration/email_validation_complete.html:22 +#: apps/registration/templates/registration/email_validation_complete.html:23 msgid "" -"The link was invalid. The token may have expired. Please send us an email to " -"activate your account." +"The link was invalid. The token may have expired, or your account is already " +"activated. However, your account seems to be already valid." msgstr "" -"Le lien est invalide. Le jeton a peut-être expiré. Merci de nous envoyer un " -"mail pour activer votre compte." +"Le lien est invalide. Le jeton a peut-être expiré, ou votre compte est déjà " +"activé. Toutefois, il semble que votre compte est déjà valide." + +#: apps/registration/templates/registration/email_validation_complete.html:25 +msgid "" +"The link was invalid. The token may have expired, or your account is already " +"activated. Please send us an email to activate your account." +msgstr "" +"Le lien est invalide. Le jeton a peut-être expiré, ou votre compte est déjà " +"activé. Merci de nous envoyer un mail pour activer votre compte." #: apps/registration/templates/registration/email_validation_email_sent.html:10 msgid "Account activation" From b761670133652214a895575d4fac47ff112a511e Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 21 Dec 2020 17:42:37 +0100 Subject: [PATCH 03/11] Rebuild search index each hour Signed-off-by: Yohann D'ANELLO --- corres2math.cron | 3 +++ 1 file changed, 3 insertions(+) diff --git a/corres2math.cron b/corres2math.cron index 1e07e98..80117f0 100644 --- a/corres2math.cron +++ b/corres2math.cron @@ -3,3 +3,6 @@ * * * * * cd /code && python manage.py send_mail -c 1 * * * * * cd /code && python manage.py retry_deferred -c 1 0 0 * * * cd /code && python manage.py purge_mail_log 7 -c 1 + +# Rebuild search index +0 * * * * cd /code && python manage.py update_index -v 0 From 8f09ca5553d042253604cd4d6a0f060dc747a8b9 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 21 Dec 2020 18:02:37 +0100 Subject: [PATCH 04/11] URLs in mails were missing domains --- .../templates/participation/mails/request_validation.html | 4 +++- .../templates/participation/mails/request_validation.txt | 2 +- apps/participation/views.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/participation/templates/participation/mails/request_validation.html b/apps/participation/templates/participation/mails/request_validation.html index 9693d0a..bc9da86 100644 --- a/apps/participation/templates/participation/mails/request_validation.html +++ b/apps/participation/templates/participation/mails/request_validation.html @@ -13,7 +13,9 @@ Bonjour {{ user.registration }}, L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer au {{ team.participation.get_problem_display }} des Correspondances des Jeunes Mathématicien·ne·s. Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe : -{% url "participation:team_detail" pk=team.pk %} + + https://{{ domain }}{% url "participation:team_detail" pk=team.pk %} +

diff --git a/apps/participation/templates/participation/mails/request_validation.txt b/apps/participation/templates/participation/mails/request_validation.txt index 6bd4f3e..522f173 100644 --- a/apps/participation/templates/participation/mails/request_validation.txt +++ b/apps/participation/templates/participation/mails/request_validation.txt @@ -3,7 +3,7 @@ Bonjour {{ user.registration }}, L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer au {{ team.participation.get_problem_display }} des Correspondances des Jeunes Mathématicien·ne·s. Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe : -{% url "participation:team_detail" pk=team.pk %} +https://{{ domain }}{% url "participation:team_detail" pk=team.pk %} Cordialement, diff --git a/apps/participation/views.py b/apps/participation/views.py index 5534278..1cb03b3 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -5,6 +5,7 @@ from corres2math.lists import get_sympa_client from corres2math.matrix import Matrix from corres2math.views import AdminMixin from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.sites.models import Site from django.core.exceptions import PermissionDenied from django.core.mail import send_mail from django.db import transaction @@ -208,7 +209,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) self.object.participation.save() for admin in AdminRegistration.objects.all(): - mail_context = dict(user=admin.user, team=self.object) + mail_context = dict(user=admin.user, team=self.object, domain=Site.objects.first().domain) mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context) mail_html = render_to_string("participation/mails/request_validation.html", mail_context) admin.user.email_user("[Corres2math] Validation d'équipe", mail_plain, html_message=mail_html) From 996d00c7f062b8c9b8d5383165ecc7eaa7004136 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 20:20:35 +0100 Subject: [PATCH 05/11] Don't send too large files --- apps/registration/forms.py | 2 + locale/fr/LC_MESSAGES/django.po | 80 +++++++++++++++++---------------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/apps/registration/forms.py b/apps/registration/forms.py index ecb2b9f..24e3588 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -72,6 +72,8 @@ class PhotoAuthorizationForm(forms.ModelForm): Form to send a photo authorization. """ def clean_photo_authorization(self): + if "photo_authorization" not in self.files: + raise ValidationError(_("The uploaded file size must be under 2 Mo.")) file = self.files["photo_authorization"] if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]: raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file.")) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index a93d97f..026d015 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Corres2math\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-11 16:09+0100\n" +"POT-Creation-Date: 2020-12-22 19:37+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -503,7 +503,7 @@ msgstr "Définir l'équipe qui recevra votre vidéo" #: apps/participation/templates/participation/participation_detail.html:181 #: apps/participation/templates/participation/participation_detail.html:233 -#: apps/participation/views.py:499 +#: apps/participation/views.py:500 msgid "Upload video" msgstr "Envoyer la vidéo" @@ -538,7 +538,7 @@ msgid "Update question" msgstr "Modifier la question" #: apps/participation/templates/participation/participation_detail.html:217 -#: apps/participation/views.py:475 +#: apps/participation/views.py:476 msgid "Delete question" msgstr "Supprimer la question" @@ -548,7 +548,7 @@ msgid "Display synthesis" msgstr "Afficher la synthèse" #: apps/participation/templates/participation/phase_list.html:10 -#: apps/participation/views.py:518 corres2math/templates/base.html:68 +#: apps/participation/views.py:519 corres2math/templates/base.html:68 #: corres2math/templates/base.html:70 corres2math/templates/base.html:226 msgid "Calendar" msgstr "Calendrier" @@ -661,7 +661,7 @@ msgid "Update team" msgstr "Modifier l'équipe" #: apps/participation/templates/participation/team_detail.html:127 -#: apps/participation/views.py:328 +#: apps/participation/views.py:329 msgid "Leave team" msgstr "Quitter l'équipe" @@ -674,49 +674,49 @@ msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?" msgid "All teams" msgstr "Toutes les équipes" -#: apps/participation/views.py:36 corres2math/templates/base.html:84 +#: apps/participation/views.py:37 corres2math/templates/base.html:84 #: corres2math/templates/base.html:241 msgid "Create team" msgstr "Créer une équipe" -#: apps/participation/views.py:43 apps/participation/views.py:89 +#: apps/participation/views.py:44 apps/participation/views.py:90 msgid "You don't participate, so you can't create a team." msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe." -#: apps/participation/views.py:45 apps/participation/views.py:91 +#: apps/participation/views.py:46 apps/participation/views.py:92 msgid "You are already in a team." msgstr "Vous êtes déjà dans une équipe." -#: apps/participation/views.py:82 corres2math/templates/base.html:89 +#: apps/participation/views.py:83 corres2math/templates/base.html:89 #: corres2math/templates/base.html:236 msgid "Join team" msgstr "Rejoindre une équipe" -#: apps/participation/views.py:142 apps/participation/views.py:334 -#: apps/participation/views.py:367 +#: apps/participation/views.py:143 apps/participation/views.py:335 +#: apps/participation/views.py:368 msgid "You are not in a team." msgstr "Vous n'êtes pas dans une équipe." -#: apps/participation/views.py:143 apps/participation/views.py:368 +#: apps/participation/views.py:144 apps/participation/views.py:369 msgid "You don't participate, so you don't have any team." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." -#: apps/participation/views.py:165 +#: apps/participation/views.py:166 #, python-brace-format msgid "Detail of team {trigram}" msgstr "Détails de l'équipe {trigram}" -#: apps/participation/views.py:197 +#: apps/participation/views.py:198 msgid "You don't participate, so you can't request the validation of the team." msgstr "" "Vous ne participez pas, vous ne pouvez pas demander la validation de " "l'équipe." -#: apps/participation/views.py:200 +#: apps/participation/views.py:201 msgid "The validation of the team is already done or pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: apps/participation/views.py:203 +#: apps/participation/views.py:204 msgid "" "The team can't be validated: missing email address confirmations, photo " "authorizations, people or the chosen problem is not set." @@ -725,51 +725,51 @@ msgstr "" "d'adresse e-mail, soit une autorisation parentale, soit des personnes soit " "le problème n'a pas été choisi." -#: apps/participation/views.py:222 +#: apps/participation/views.py:223 msgid "You are not an administrator." msgstr "Vous n'êtes pas administrateur." -#: apps/participation/views.py:225 +#: apps/participation/views.py:226 msgid "This team has no pending validation." msgstr "L'équipe n'a pas de validation en attente." -#: apps/participation/views.py:249 +#: apps/participation/views.py:250 msgid "You must specify if you validate the registration or not." msgstr "Vous devez spécifier si vous validez l'inscription ou non." -#: apps/participation/views.py:277 +#: apps/participation/views.py:278 #, python-brace-format msgid "Update team {trigram}" msgstr "Mise à jour de l'équipe {trigram}" -#: apps/participation/views.py:314 apps/registration/views.py:284 +#: apps/participation/views.py:315 apps/registration/views.py:283 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}" -#: apps/participation/views.py:318 +#: apps/participation/views.py:319 #, python-brace-format msgid "Photo authorizations of team {trigram}.zip" msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip" -#: apps/participation/views.py:336 +#: apps/participation/views.py:337 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: apps/participation/views.py:380 +#: apps/participation/views.py:381 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: apps/participation/views.py:390 +#: apps/participation/views.py:391 #, python-brace-format msgid "Participation of team {trigram}" msgstr "Participation de l'équipe {trigram}" -#: apps/participation/views.py:427 +#: apps/participation/views.py:428 msgid "Create question" msgstr "Créer une question" -#: apps/participation/views.py:527 +#: apps/participation/views.py:528 msgid "Calendar update" msgstr "Mise à jour du calendrier" @@ -789,7 +789,11 @@ msgstr "encadrant" msgid "This email address is already used." msgstr "Cette adresse e-mail est déjà utilisée." -#: apps/registration/forms.py:77 +#: apps/registration/forms.py:76 +msgid "The uploaded file size must be under 2 Mo." +msgstr "Le fichier envoyé doit peser moins de 2 Mo." + +#: apps/registration/forms.py:79 msgid "The uploaded file must be a PDF, PNG of JPEG file." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." @@ -1032,7 +1036,7 @@ msgstr "Réinitialiser mon mot de passe" #: apps/registration/templates/registration/signup.html:5 #: apps/registration/templates/registration/signup.html:8 #: apps/registration/templates/registration/signup.html:20 -#: apps/registration/views.py:33 +#: apps/registration/views.py:32 msgid "Sign up" msgstr "Inscription" @@ -1109,40 +1113,40 @@ msgid "Update user" msgstr "Modifier l'utilisateur" #: apps/registration/templates/registration/user_detail.html:77 -#: apps/registration/views.py:247 +#: apps/registration/views.py:246 msgid "Upload photo authorization" msgstr "Téléverser l'autorisation de droit à l'image" -#: apps/registration/views.py:41 +#: apps/registration/views.py:40 msgid "You can't register now." msgstr "Vous ne pouvez pas vous inscrire maintenant." -#: apps/registration/views.py:85 +#: apps/registration/views.py:84 msgid "Email validation" msgstr "Validation de l'adresse mail" -#: apps/registration/views.py:87 +#: apps/registration/views.py:86 msgid "Validate email" msgstr "Valider l'adresse mail" -#: apps/registration/views.py:126 +#: apps/registration/views.py:125 msgid "Email validation unsuccessful" msgstr "Échec de la validation de l'adresse mail" -#: apps/registration/views.py:137 +#: apps/registration/views.py:136 msgid "Email validation email sent" msgstr "Mail de confirmation de l'adresse mail envoyé" -#: apps/registration/views.py:145 +#: apps/registration/views.py:144 msgid "Resend email validation link" msgstr "Renvoyé le lien de validation de l'adresse mail" -#: apps/registration/views.py:181 +#: apps/registration/views.py:180 #, python-brace-format msgid "Detail of user {user}" msgstr "Détails de l'utilisateur {user}" -#: apps/registration/views.py:211 +#: apps/registration/views.py:210 #, python-brace-format msgid "Update user {user}" msgstr "Mise à jour de l'utilisateur {user}" From 8f742b8e1487c70999f51eaf9d2df47942e9f91f Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 20:40:01 +0100 Subject: [PATCH 06/11] Increase nginx upload limit to have a better message in the Django form --- apps/registration/forms.py | 13 +++++++------ nginx_corres2math.conf | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 24e3588..5c4aec3 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -72,12 +72,13 @@ class PhotoAuthorizationForm(forms.ModelForm): Form to send a photo authorization. """ def clean_photo_authorization(self): - if "photo_authorization" not in self.files: - raise ValidationError(_("The uploaded file size must be under 2 Mo.")) - file = self.files["photo_authorization"] - if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]: - raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file.")) - return self.cleaned_data["photo_authorization"] + if "photo_authorization" in self.files: + file = self.files["photo_authorization"] + if file.size > 2e6: + raise ValidationError(_("The uploaded file size must be under 2 Mo.")) + if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]: + raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file.")) + return self.cleaned_data["photo_authorization"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/nginx_corres2math.conf b/nginx_corres2math.conf index e4b01f0..06900b2 100644 --- a/nginx_corres2math.conf +++ b/nginx_corres2math.conf @@ -5,6 +5,7 @@ upstream corres2math { server { listen 80; server_name corres2math; + client_max_body_size 50M; location / { proxy_pass http://corres2math; From 205760f2e9884cf4c9211e5d52b39ab5be8129f7 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 20:47:43 +0100 Subject: [PATCH 07/11] More protection on pages that require authentication --- apps/participation/tests.py | 2 +- apps/participation/views.py | 12 ++++++++++++ apps/registration/tests.py | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apps/participation/tests.py b/apps/participation/tests.py index b1b7bd2..82a0309 100644 --- a/apps/participation/tests.py +++ b/apps/participation/tests.py @@ -669,7 +669,7 @@ class TestStudentParticipation(TestCase): def test_forbidden_access(self): """ - Load personnal pages and ensure that these are protected. + Load personal pages and ensure that these are protected. """ self.user.registration.team = self.team self.user.registration.save() diff --git a/apps/participation/views.py b/apps/participation/views.py index 1cb03b3..34e2cf0 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -39,6 +39,8 @@ class CreateTeamView(LoginRequiredMixin, CreateView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() registration = user.registration if not registration.participates: raise PermissionDenied(_("You don't participate, so you can't create a team.")) @@ -85,6 +87,8 @@ class JoinTeamView(LoginRequiredMixin, FormView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() registration = user.registration if not registration.participates: raise PermissionDenied(_("You don't participate, so you can't create a team.")) @@ -265,6 +269,8 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() if user.registration.is_admin or user.registration.participates and \ user.registration.team and \ user.registration.team.pk == kwargs["pk"]: @@ -299,6 +305,8 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: return super().dispatch(request, *args, **kwargs) raise PermissionDenied @@ -377,6 +385,8 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() if not self.get_object().valid: raise PermissionDenied(_("The team is not validated yet.")) if user.registration.is_admin or user.registration.participates \ @@ -501,6 +511,8 @@ class UploadVideoView(LoginRequiredMixin, UpdateView): def dispatch(self, request, *args, **kwargs): user = request.user + if not user.is_authenticated: + return super().handle_no_permission() if user.registration.is_admin or user.registration.participates \ and user.registration.team.participation.pk == self.get_object().participation.pk: return super().dispatch(request, *args, **kwargs) diff --git a/apps/registration/tests.py b/apps/registration/tests.py index f33dc97..ad1ddc2 100644 --- a/apps/registration/tests.py +++ b/apps/registration/tests.py @@ -11,7 +11,7 @@ from django.urls import reverse from django.utils import timezone from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode -from participation.models import Phase +from participation.models import Phase, Team from .models import AdminRegistration, CoachRegistration, StudentRegistration @@ -35,6 +35,24 @@ class TestIndexPage(TestCase): response = self.client.get(reverse("registration:user_detail", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("registration:user_detail", args=(1,))) + Team.objects.create() + response = self.client.get(reverse("participation:team_detail", args=(1,))) + self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:team_detail", args=(1,))) + response = self.client.get(reverse("participation:update_team", args=(1,))) + self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:update_team", args=(1,))) + response = self.client.get(reverse("participation:create_team")) + self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:create_team")) + response = self.client.get(reverse("participation:join_team")) + self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:join_team")) + response = self.client.get(reverse("participation:team_authorizations", args=(1,))) + self.assertRedirects(response, reverse("login") + "?next=" + + reverse("participation:team_authorizations", args=(1,))) + response = self.client.get(reverse("participation:participation_detail", args=(1,))) + self.assertRedirects(response, reverse("login") + "?next=" + + reverse("participation:participation_detail", args=(1,))) + response = self.client.get(reverse("participation:upload_video", args=(1,))) + self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:upload_video", args=(1,))) + class TestRegistration(TestCase): def setUp(self) -> None: From 1f9f60d880df78efef58d33b4de4a835bb054d71 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 20:57:03 +0100 Subject: [PATCH 08/11] Unit test for large files uploading --- apps/registration/tests.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/registration/tests.py b/apps/registration/tests.py index ad1ddc2..1ce4bea 100644 --- a/apps/registration/tests.py +++ b/apps/registration/tests.py @@ -1,6 +1,8 @@ from datetime import timedelta import os +from django.core.files.uploadedfile import SimpleUploadedFile + from corres2math.tokens import email_validation_token from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType @@ -286,6 +288,14 @@ class TestRegistration(TestCase): )) self.assertEqual(response.status_code, 200) + # Don't send too large files + response = self.client.post(reverse("registration:upload_user_photo_authorization", + args=(self.student.registration.pk,)), data=dict( + photo_authorization=SimpleUploadedFile("file.pdf",content=int(0).to_bytes(2000001, "big"), + content_type="application/pdf"), + )) + self.assertEqual(response.status_code, 200) + response = self.client.post(reverse("registration:upload_user_photo_authorization", args=(self.student.registration.pk,)), data=dict( photo_authorization=open("corres2math/static/Autorisation de droit à l'image - majeur.pdf", "rb"), From 9e6a3eb1ca31fe8f1fc04e0e4f6d9c2d8168a07a Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 21:06:11 +0100 Subject: [PATCH 09/11] Add Gitlab logo --- corres2math/templates/base.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/corres2math/templates/base.html b/corres2math/templates/base.html index a06cf17..e51ff81 100644 --- a/corres2math/templates/base.html +++ b/corres2math/templates/base.html @@ -192,7 +192,7 @@ class="form-inline"> {% trans "Contact us" %} — + class="text-muted"> {% trans "Contact us" %} {% csrf_token %} +   +   + + +

From 84e149e8c9213bb0d1d27ef8c3020728dff71af4 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 21:28:30 +0100 Subject: [PATCH 10/11] Add about page --- corres2math/templates/about.html | 40 ++++++++++++++++ corres2math/templates/base.html | 3 +- corres2math/urls.py | 3 +- locale/fr/LC_MESSAGES/django.po | 78 +++++++++++++++++--------------- 4 files changed, 85 insertions(+), 39 deletions(-) create mode 100644 corres2math/templates/about.html diff --git a/corres2math/templates/about.html b/corres2math/templates/about.html new file mode 100644 index 0000000..963afea --- /dev/null +++ b/corres2math/templates/about.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} + +{% block contenttitle %} +

À propos

+{% endblock %} + +{% block content %} +

+ La plateforme d'inscription des Correspondances des Jeunes Mathématiciennes a été développée entre 2019 et 2021 + par Yohann D'ANELLO, bénévole pour l'association Animath. Elle est vouée à être utilisée par les participants + pour intéragir avec les organisateurs et les autres participants. +

+ +

+ La plateforme est développée avec le framework Django et le code + source est accessible librement sur Gitlab. + Le code est distribué sous la licence GNU GPL v3, + qui vous autorise à consulter le code, à le partager, à réutiliser des parties du code et à contribuer. +

+ +

+ Le site principal présent sur https://inscription.correspondances-maths.fr + est hébergé chez Scaleway. +

+ +

+ Les données collectées par cette plateforme sont utilisées uniquement dans le cadre des Correspondances et sont + détruites dès l'action touche à sa fin, soit au plus tard 1 an après le début de l'action. Sur autorisation + explicite, des informations de contact peuvent être conservées afin d'être tenu au courant des actions futures + de l'association Animath. Aucune information personnelle n'est collectée à votre insu. Aucune information + personnelle n'est cédée à des tiers. +

+ +

+ Pour toute demande ou réclammation, merci de nous contacter à l'adresse + + contact@correspondances-maths.fr + . +

+{% endblock %} diff --git a/corres2math/templates/base.html b/corres2math/templates/base.html index e51ff81..9f24a75 100644 --- a/corres2math/templates/base.html +++ b/corres2math/templates/base.html @@ -192,7 +192,7 @@ class="form-inline"> {% trans "Contact us" %} + class="text-muted"> {% trans "Contact us" %} {% csrf_token %}   + {% trans "About" %}   —   diff --git a/corres2math/urls.py b/corres2math/urls.py index 1947023..910f4eb 100644 --- a/corres2math/urls.py +++ b/corres2math/urls.py @@ -23,7 +23,8 @@ from registration.views import PhotoAuthorizationView from .views import AdminSearchView urlpatterns = [ - path('', TemplateView.as_view(template_name="index.html", extra_context=dict(title="Accueil")), name='index'), + path('', TemplateView.as_view(template_name="index.html"), name='index'), + path('about/', TemplateView.as_view(template_name="about.html"), name='about'), path('i18n/', include('django.conf.urls.i18n')), path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/', admin.site.urls, name="admin"), diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 026d015..b427723 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Corres2math\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-22 19:37+0100\n" +"POT-Creation-Date: 2020-12-22 21:30+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -324,12 +324,12 @@ msgstr "" "contacter :)" #: apps/participation/templates/participation/create_team.html:11 -#: corres2math/templates/base.html:242 +#: corres2math/templates/base.html:247 msgid "Create" msgstr "Créer" #: apps/participation/templates/participation/join_team.html:11 -#: corres2math/templates/base.html:237 +#: corres2math/templates/base.html:242 msgid "Join" msgstr "Rejoindre" @@ -503,7 +503,7 @@ msgstr "Définir l'équipe qui recevra votre vidéo" #: apps/participation/templates/participation/participation_detail.html:181 #: apps/participation/templates/participation/participation_detail.html:233 -#: apps/participation/views.py:500 +#: apps/participation/views.py:510 msgid "Upload video" msgstr "Envoyer la vidéo" @@ -538,7 +538,7 @@ msgid "Update question" msgstr "Modifier la question" #: apps/participation/templates/participation/participation_detail.html:217 -#: apps/participation/views.py:476 +#: apps/participation/views.py:486 msgid "Delete question" msgstr "Supprimer la question" @@ -548,8 +548,8 @@ msgid "Display synthesis" msgstr "Afficher la synthèse" #: apps/participation/templates/participation/phase_list.html:10 -#: apps/participation/views.py:519 corres2math/templates/base.html:68 -#: corres2math/templates/base.html:70 corres2math/templates/base.html:226 +#: apps/participation/views.py:531 corres2math/templates/base.html:68 +#: corres2math/templates/base.html:70 corres2math/templates/base.html:231 msgid "Calendar" msgstr "Calendrier" @@ -661,7 +661,7 @@ msgid "Update team" msgstr "Modifier l'équipe" #: apps/participation/templates/participation/team_detail.html:127 -#: apps/participation/views.py:329 +#: apps/participation/views.py:337 msgid "Leave team" msgstr "Quitter l'équipe" @@ -670,53 +670,53 @@ msgid "Are you sure that you want to leave this team?" msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?" #: apps/participation/templates/participation/team_list.html:6 -#: corres2math/templates/base.html:230 +#: corres2math/templates/base.html:235 msgid "All teams" msgstr "Toutes les équipes" #: apps/participation/views.py:37 corres2math/templates/base.html:84 -#: corres2math/templates/base.html:241 +#: corres2math/templates/base.html:246 msgid "Create team" msgstr "Créer une équipe" -#: apps/participation/views.py:44 apps/participation/views.py:90 +#: apps/participation/views.py:46 apps/participation/views.py:94 msgid "You don't participate, so you can't create a team." msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe." -#: apps/participation/views.py:46 apps/participation/views.py:92 +#: apps/participation/views.py:48 apps/participation/views.py:96 msgid "You are already in a team." msgstr "Vous êtes déjà dans une équipe." -#: apps/participation/views.py:83 corres2math/templates/base.html:89 -#: corres2math/templates/base.html:236 +#: apps/participation/views.py:85 corres2math/templates/base.html:89 +#: corres2math/templates/base.html:241 msgid "Join team" msgstr "Rejoindre une équipe" -#: apps/participation/views.py:143 apps/participation/views.py:335 -#: apps/participation/views.py:368 +#: apps/participation/views.py:147 apps/participation/views.py:343 +#: apps/participation/views.py:376 msgid "You are not in a team." msgstr "Vous n'êtes pas dans une équipe." -#: apps/participation/views.py:144 apps/participation/views.py:369 +#: apps/participation/views.py:148 apps/participation/views.py:377 msgid "You don't participate, so you don't have any team." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." -#: apps/participation/views.py:166 +#: apps/participation/views.py:170 #, python-brace-format msgid "Detail of team {trigram}" msgstr "Détails de l'équipe {trigram}" -#: apps/participation/views.py:198 +#: apps/participation/views.py:202 msgid "You don't participate, so you can't request the validation of the team." msgstr "" "Vous ne participez pas, vous ne pouvez pas demander la validation de " "l'équipe." -#: apps/participation/views.py:201 +#: apps/participation/views.py:205 msgid "The validation of the team is already done or pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: apps/participation/views.py:204 +#: apps/participation/views.py:208 msgid "" "The team can't be validated: missing email address confirmations, photo " "authorizations, people or the chosen problem is not set." @@ -725,51 +725,51 @@ msgstr "" "d'adresse e-mail, soit une autorisation parentale, soit des personnes soit " "le problème n'a pas été choisi." -#: apps/participation/views.py:223 +#: apps/participation/views.py:227 msgid "You are not an administrator." msgstr "Vous n'êtes pas administrateur." -#: apps/participation/views.py:226 +#: apps/participation/views.py:230 msgid "This team has no pending validation." msgstr "L'équipe n'a pas de validation en attente." -#: apps/participation/views.py:250 +#: apps/participation/views.py:254 msgid "You must specify if you validate the registration or not." msgstr "Vous devez spécifier si vous validez l'inscription ou non." -#: apps/participation/views.py:278 +#: apps/participation/views.py:284 #, python-brace-format msgid "Update team {trigram}" msgstr "Mise à jour de l'équipe {trigram}" -#: apps/participation/views.py:315 apps/registration/views.py:283 +#: apps/participation/views.py:323 apps/registration/views.py:283 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}" -#: apps/participation/views.py:319 +#: apps/participation/views.py:327 #, python-brace-format msgid "Photo authorizations of team {trigram}.zip" msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip" -#: apps/participation/views.py:337 +#: apps/participation/views.py:345 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: apps/participation/views.py:381 +#: apps/participation/views.py:391 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: apps/participation/views.py:391 +#: apps/participation/views.py:401 #, python-brace-format msgid "Participation of team {trigram}" msgstr "Participation de l'équipe {trigram}" -#: apps/participation/views.py:428 +#: apps/participation/views.py:438 msgid "Create question" msgstr "Créer une question" -#: apps/participation/views.py:528 +#: apps/participation/views.py:540 msgid "Calendar update" msgstr "Mise à jour du calendrier" @@ -789,11 +789,11 @@ msgstr "encadrant" msgid "This email address is already used." msgstr "Cette adresse e-mail est déjà utilisée." -#: apps/registration/forms.py:76 +#: apps/registration/forms.py:78 msgid "The uploaded file size must be under 2 Mo." msgstr "Le fichier envoyé doit peser moins de 2 Mo." -#: apps/registration/forms.py:79 +#: apps/registration/forms.py:80 msgid "The uploaded file must be a PDF, PNG of JPEG file." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." @@ -978,8 +978,8 @@ msgid "Your password has been set. You may go ahead and log in now." msgstr "Votre mot de passe a été changé. Vous pouvez désormais vous connecter." #: apps/registration/templates/registration/password_reset_complete.html:10 -#: corres2math/templates/base.html:139 corres2math/templates/base.html:246 -#: corres2math/templates/base.html:247 +#: corres2math/templates/base.html:139 corres2math/templates/base.html:251 +#: corres2math/templates/base.html:252 #: corres2math/templates/registration/login.html:7 #: corres2math/templates/registration/login.html:8 #: corres2math/templates/registration/login.html:25 @@ -1275,7 +1275,11 @@ msgstr "" msgid "Contact us" msgstr "Nous contacter" -#: corres2math/templates/base.html:233 +#: corres2math/templates/base.html:214 +msgid "About" +msgstr "À propos" + +#: corres2math/templates/base.html:238 msgid "Search results" msgstr "Résultats de la recherche" From 969e53b71230a65fe25d0747580321cf938c3fd1 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 22 Dec 2020 21:31:22 +0100 Subject: [PATCH 11/11] Linting --- apps/registration/tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/registration/tests.py b/apps/registration/tests.py index 1ce4bea..4f3ff34 100644 --- a/apps/registration/tests.py +++ b/apps/registration/tests.py @@ -1,12 +1,11 @@ from datetime import timedelta import os -from django.core.files.uploadedfile import SimpleUploadedFile - from corres2math.tokens import email_validation_token from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.sites.models import Site +from django.core.files.uploadedfile import SimpleUploadedFile from django.core.management import call_command from django.test import TestCase from django.urls import reverse @@ -291,7 +290,7 @@ class TestRegistration(TestCase): # Don't send too large files response = self.client.post(reverse("registration:upload_user_photo_authorization", args=(self.student.registration.pk,)), data=dict( - photo_authorization=SimpleUploadedFile("file.pdf",content=int(0).to_bytes(2000001, "big"), + photo_authorization=SimpleUploadedFile("file.pdf", content=int(0).to_bytes(2000001, "big"), content_type="application/pdf"), )) self.assertEqual(response.status_code, 200)