1
0
mirror of https://gitlab.com/animath/si/plateforme-corres2math.git synced 2025-02-12 15:41:18 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Yohann D'ANELLO
9e6a3eb1ca
Add Gitlab logo 2020-12-22 21:06:11 +01:00
Yohann D'ANELLO
1f9f60d880
Unit test for large files uploading 2020-12-22 20:57:03 +01:00
Yohann D'ANELLO
205760f2e9
More protection on pages that require authentication 2020-12-22 20:48:25 +01:00
Yohann D'ANELLO
8f742b8e14
Increase nginx upload limit to have a better message in the Django form 2020-12-22 20:40:01 +01:00
Yohann D'ANELLO
996d00c7f0
Don't send too large files 2020-12-22 20:20:35 +01:00
7 changed files with 99 additions and 47 deletions

View File

@ -669,7 +669,7 @@ class TestStudentParticipation(TestCase):
def test_forbidden_access(self): 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.team = self.team
self.user.registration.save() self.user.registration.save()

View File

@ -39,6 +39,8 @@ class CreateTeamView(LoginRequiredMixin, CreateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
registration = user.registration registration = user.registration
if not registration.participates: if not registration.participates:
raise PermissionDenied(_("You don't participate, so you can't create a team.")) 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): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
registration = user.registration registration = user.registration
if not registration.participates: if not registration.participates:
raise PermissionDenied(_("You don't participate, so you can't create a team.")) 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): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if user.registration.is_admin or user.registration.participates and \ if user.registration.is_admin or user.registration.participates and \
user.registration.team and \ user.registration.team and \
user.registration.team.pk == kwargs["pk"]: user.registration.team.pk == kwargs["pk"]:
@ -299,6 +305,8 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
user = request.user 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"]: if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
raise PermissionDenied raise PermissionDenied
@ -377,6 +385,8 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if not self.get_object().valid: if not self.get_object().valid:
raise PermissionDenied(_("The team is not validated yet.")) raise PermissionDenied(_("The team is not validated yet."))
if user.registration.is_admin or user.registration.participates \ if user.registration.is_admin or user.registration.participates \
@ -501,6 +511,8 @@ class UploadVideoView(LoginRequiredMixin, UpdateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if user.registration.is_admin or user.registration.participates \ if user.registration.is_admin or user.registration.participates \
and user.registration.team.participation.pk == self.get_object().participation.pk: and user.registration.team.participation.pk == self.get_object().participation.pk:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

View File

@ -72,7 +72,10 @@ class PhotoAuthorizationForm(forms.ModelForm):
Form to send a photo authorization. Form to send a photo authorization.
""" """
def clean_photo_authorization(self): def clean_photo_authorization(self):
if "photo_authorization" in self.files:
file = self.files["photo_authorization"] 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"]: 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.")) raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
return self.cleaned_data["photo_authorization"] return self.cleaned_data["photo_authorization"]

View File

@ -1,6 +1,8 @@
from datetime import timedelta from datetime import timedelta
import os import os
from django.core.files.uploadedfile import SimpleUploadedFile
from corres2math.tokens import email_validation_token from corres2math.tokens import email_validation_token
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -11,7 +13,7 @@ from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode 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 from .models import AdminRegistration, CoachRegistration, StudentRegistration
@ -35,6 +37,24 @@ class TestIndexPage(TestCase):
response = self.client.get(reverse("registration:user_detail", args=(1,))) response = self.client.get(reverse("registration:user_detail", args=(1,)))
self.assertRedirects(response, reverse("login") + "?next=" + 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): class TestRegistration(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
@ -268,6 +288,14 @@ class TestRegistration(TestCase):
)) ))
self.assertEqual(response.status_code, 200) 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", response = self.client.post(reverse("registration:upload_user_photo_authorization",
args=(self.student.registration.pk,)), data=dict( args=(self.student.registration.pk,)), data=dict(
photo_authorization=open("corres2math/static/Autorisation de droit à l'image - majeur.pdf", "rb"), photo_authorization=open("corres2math/static/Autorisation de droit à l'image - majeur.pdf", "rb"),

View File

@ -192,7 +192,7 @@
class="form-inline"> class="form-inline">
<span class="text-muted mr-1"> <span class="text-muted mr-1">
<a target="_blank" href="mailto:&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#99;&#111;&#114;&#114;&#101;&#115;&#112;&#111;&#110;&#100;&#97;&#110;&#99;&#101;&#115;&#45;&#109;&#97;&#116;&#104;&#115;&#46;&#102;&#114;" <a target="_blank" href="mailto:&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#99;&#111;&#114;&#114;&#101;&#115;&#112;&#111;&#110;&#100;&#97;&#110;&#99;&#101;&#115;&#45;&#109;&#97;&#116;&#104;&#115;&#46;&#102;&#114;"
class="text-muted">{% trans "Contact us" %}</a> &mdash; class="text-muted"><i class="fas fa-mail-forward"></i> {% trans "Contact us" %}</a>
</span> </span>
{% csrf_token %} {% csrf_token %}
<select title="language" name="language" <select title="language" name="language"
@ -207,10 +207,14 @@
{{ lang_name }} ({{ lang_code }}) {{ lang_name }} ({{ lang_code }})
</option> </option>
{% endfor %} {% endfor %}
</select> </select> &nbsp;
<noscript> <noscript>
<input type="submit"> <input type="submit">
</noscript> </noscript> &nbsp;
<a target="_blank" class="text-muted"
href="https://gitlab.com/animath/si/plateforme-corres2math">
<i class="fab fa-gitlab"></i>
</a>
</form> </form>
</div> </div>
<div class="col text-right"> <div class="col text-right">

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Corres2math\n" "Project-Id-Version: Corres2math\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n" "Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\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:181
#: apps/participation/templates/participation/participation_detail.html:233 #: apps/participation/templates/participation/participation_detail.html:233
#: apps/participation/views.py:499 #: apps/participation/views.py:500
msgid "Upload video" msgid "Upload video"
msgstr "Envoyer la vidéo" msgstr "Envoyer la vidéo"
@ -538,7 +538,7 @@ msgid "Update question"
msgstr "Modifier la question" msgstr "Modifier la question"
#: apps/participation/templates/participation/participation_detail.html:217 #: apps/participation/templates/participation/participation_detail.html:217
#: apps/participation/views.py:475 #: apps/participation/views.py:476
msgid "Delete question" msgid "Delete question"
msgstr "Supprimer la question" msgstr "Supprimer la question"
@ -548,7 +548,7 @@ msgid "Display synthesis"
msgstr "Afficher la synthèse" msgstr "Afficher la synthèse"
#: apps/participation/templates/participation/phase_list.html:10 #: 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 #: corres2math/templates/base.html:70 corres2math/templates/base.html:226
msgid "Calendar" msgid "Calendar"
msgstr "Calendrier" msgstr "Calendrier"
@ -661,7 +661,7 @@ msgid "Update team"
msgstr "Modifier l'équipe" msgstr "Modifier l'équipe"
#: apps/participation/templates/participation/team_detail.html:127 #: apps/participation/templates/participation/team_detail.html:127
#: apps/participation/views.py:328 #: apps/participation/views.py:329
msgid "Leave team" msgid "Leave team"
msgstr "Quitter l'équipe" msgstr "Quitter l'équipe"
@ -674,49 +674,49 @@ msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?"
msgid "All teams" msgid "All teams"
msgstr "Toutes les équipes" 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 #: corres2math/templates/base.html:241
msgid "Create team" msgid "Create team"
msgstr "Créer une équipe" 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." 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." 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." msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe." 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 #: corres2math/templates/base.html:236
msgid "Join team" msgid "Join team"
msgstr "Rejoindre une équipe" msgstr "Rejoindre une équipe"
#: apps/participation/views.py:142 apps/participation/views.py:334 #: apps/participation/views.py:143 apps/participation/views.py:335
#: apps/participation/views.py:367 #: apps/participation/views.py:368
msgid "You are not in a team." msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe." 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." msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." 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 #, python-brace-format
msgid "Detail of team {trigram}" msgid "Detail of team {trigram}"
msgstr "Détails de l'équipe {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." msgid "You don't participate, so you can't request the validation of the team."
msgstr "" msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de " "Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe." "l'équipe."
#: apps/participation/views.py:200 #: apps/participation/views.py:201
msgid "The validation of the team is already done or pending." msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours." msgstr "La validation de l'équipe est déjà faite ou en cours."
#: apps/participation/views.py:203 #: apps/participation/views.py:204
msgid "" msgid ""
"The team can't be validated: missing email address confirmations, photo " "The team can't be validated: missing email address confirmations, photo "
"authorizations, people or the chosen problem is not set." "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 " "d'adresse e-mail, soit une autorisation parentale, soit des personnes soit "
"le problème n'a pas été choisi." "le problème n'a pas été choisi."
#: apps/participation/views.py:222 #: apps/participation/views.py:223
msgid "You are not an administrator." msgid "You are not an administrator."
msgstr "Vous n'êtes pas administrateur." msgstr "Vous n'êtes pas administrateur."
#: apps/participation/views.py:225 #: apps/participation/views.py:226
msgid "This team has no pending validation." msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente." 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." msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non." 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 #, python-brace-format
msgid "Update team {trigram}" msgid "Update team {trigram}"
msgstr "Mise à jour de l'équipe {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 #, python-brace-format
msgid "Photo authorization of {student}.{ext}" msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}"
#: apps/participation/views.py:318 #: apps/participation/views.py:319
#, python-brace-format #, python-brace-format
msgid "Photo authorizations of team {trigram}.zip" msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {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." msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours." 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." msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée." msgstr "L'équipe n'est pas encore validée."
#: apps/participation/views.py:390 #: apps/participation/views.py:391
#, python-brace-format #, python-brace-format
msgid "Participation of team {trigram}" msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}" msgstr "Participation de l'équipe {trigram}"
#: apps/participation/views.py:427 #: apps/participation/views.py:428
msgid "Create question" msgid "Create question"
msgstr "Créer une question" msgstr "Créer une question"
#: apps/participation/views.py:527 #: apps/participation/views.py:528
msgid "Calendar update" msgid "Calendar update"
msgstr "Mise à jour du calendrier" msgstr "Mise à jour du calendrier"
@ -789,7 +789,11 @@ msgstr "encadrant"
msgid "This email address is already used." msgid "This email address is already used."
msgstr "Cette adresse e-mail est déjà utilisée." 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." msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." 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:5
#: apps/registration/templates/registration/signup.html:8 #: apps/registration/templates/registration/signup.html:8
#: apps/registration/templates/registration/signup.html:20 #: apps/registration/templates/registration/signup.html:20
#: apps/registration/views.py:33 #: apps/registration/views.py:32
msgid "Sign up" msgid "Sign up"
msgstr "Inscription" msgstr "Inscription"
@ -1109,40 +1113,40 @@ msgid "Update user"
msgstr "Modifier l'utilisateur" msgstr "Modifier l'utilisateur"
#: apps/registration/templates/registration/user_detail.html:77 #: apps/registration/templates/registration/user_detail.html:77
#: apps/registration/views.py:247 #: apps/registration/views.py:246
msgid "Upload photo authorization" msgid "Upload photo authorization"
msgstr "Téléverser l'autorisation de droit à l'image" 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." msgid "You can't register now."
msgstr "Vous ne pouvez pas vous inscrire maintenant." msgstr "Vous ne pouvez pas vous inscrire maintenant."
#: apps/registration/views.py:85 #: apps/registration/views.py:84
msgid "Email validation" msgid "Email validation"
msgstr "Validation de l'adresse mail" msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:87 #: apps/registration/views.py:86
msgid "Validate email" msgid "Validate email"
msgstr "Valider l'adresse mail" msgstr "Valider l'adresse mail"
#: apps/registration/views.py:126 #: apps/registration/views.py:125
msgid "Email validation unsuccessful" msgid "Email validation unsuccessful"
msgstr "Échec de la validation de l'adresse mail" msgstr "Échec de la validation de l'adresse mail"
#: apps/registration/views.py:137 #: apps/registration/views.py:136
msgid "Email validation email sent" msgid "Email validation email sent"
msgstr "Mail de confirmation de l'adresse mail envoyé" msgstr "Mail de confirmation de l'adresse mail envoyé"
#: apps/registration/views.py:145 #: apps/registration/views.py:144
msgid "Resend email validation link" msgid "Resend email validation link"
msgstr "Renvoyé le lien de validation de l'adresse mail" msgstr "Renvoyé le lien de validation de l'adresse mail"
#: apps/registration/views.py:181 #: apps/registration/views.py:180
#, python-brace-format #, python-brace-format
msgid "Detail of user {user}" msgid "Detail of user {user}"
msgstr "Détails de l'utilisateur {user}" msgstr "Détails de l'utilisateur {user}"
#: apps/registration/views.py:211 #: apps/registration/views.py:210
#, python-brace-format #, python-brace-format
msgid "Update user {user}" msgid "Update user {user}"
msgstr "Mise à jour de l'utilisateur {user}" msgstr "Mise à jour de l'utilisateur {user}"

View File

@ -5,6 +5,7 @@ upstream corres2math {
server { server {
listen 80; listen 80;
server_name corres2math; server_name corres2math;
client_max_body_size 50M;
location / { location / {
proxy_pass http://corres2math; proxy_pass http://corres2math;