mirror of
https://gitlab.com/animath/si/plateforme-corres2math.git
synced 2025-07-06 08:43:53 +02:00
Merge branch 'improvements' into 'master'
Improvements, bug fixes See merge request animath/si/plateforme-corres2math!8
This commit is contained in:
@ -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 :
|
||||
<a href="{% url "participation:team_detail" pk=team.pk %}">{% url "participation:team_detail" pk=team.pk %}</a>
|
||||
<a href="https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}">
|
||||
https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
@ -38,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."))
|
||||
@ -84,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."))
|
||||
@ -208,7 +213,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)
|
||||
@ -264,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"]:
|
||||
@ -298,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
|
||||
@ -376,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 \
|
||||
@ -500,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)
|
||||
|
@ -72,10 +72,13 @@ class PhotoAuthorizationForm(forms.ModelForm):
|
||||
Form to send a photo authorization.
|
||||
"""
|
||||
def clean_photo_authorization(self):
|
||||
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)
|
||||
|
@ -19,7 +19,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
{% 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 %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -5,13 +5,14 @@ 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
|
||||
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 +36,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:
|
||||
@ -268,6 +287,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"),
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user