From 88c4a6b218ead1b6f3ecf567184cf4c71913a921 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sun, 27 Sep 2020 16:35:31 +0200 Subject: [PATCH] Protect some pages --- apps/participation/views.py | 57 ++++++++--- apps/registration/models.py | 4 + .../templates/registration/user_detail.html | 23 ++++- apps/registration/views.py | 23 ++++- locale/fr/LC_MESSAGES/django.po | 94 ++++++++++--------- 5 files changed, 136 insertions(+), 65 deletions(-) diff --git a/apps/participation/views.py b/apps/participation/views.py index a79c8f1..7d4da87 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -15,18 +15,20 @@ class CreateTeamView(LoginRequiredMixin, CreateView): extra_context = dict(title=_("Create team")) template_name = "participation/create_team.html" - @transaction.atomic - def form_valid(self, form): - user = self.request.user + def dispatch(self, request, *args, **kwargs): + user = request.user registration = user.registration if not registration.participates: - form.add_error(None, _("You don't participate, so you can't create a team.")) - return self.form_invalid(form) + raise PermissionDenied(_("You don't participate, so you can't create a team.")) elif registration.team: - form.add_error(None, _("You are already in a team.")) - return self.form_invalid(form) + raise PermissionDenied(_("You are already in a team.")) + return super().dispatch(request, *args, **kwargs) + @transaction.atomic + def form_valid(self, form): ret = super().form_valid(form) + user = self.request.user + registration = user.registration registration.team = form.instance registration.save() return ret @@ -41,19 +43,21 @@ class JoinTeamView(LoginRequiredMixin, FormView): extra_context = dict(title=_("Join team")) template_name = "participation/create_team.html" - @transaction.atomic - def form_valid(self, form): - user = self.request.user + def dispatch(self, request, *args, **kwargs): + user = request.user registration = user.registration if not registration.participates: - form.add_error(None, _("You don't participate, so you can't create a team.")) - return self.form_invalid(form) + raise PermissionDenied(_("You don't participate, so you can't create a team.")) elif registration.team: - form.add_error(None, _("You are already in a team.")) - return self.form_invalid(form) + raise PermissionDenied(_("You are already in a team.")) + return super().dispatch(request, *args, **kwargs) + @transaction.atomic + def form_valid(self, form): self.object = form.instance ret = super().form_valid(form) + user = self.request.user + registration = user.registration registration.team = form.instance registration.save() return ret @@ -76,12 +80,24 @@ class MyTeamDetailView(LoginRequiredMixin, RedirectView): class TeamDetailView(LoginRequiredMixin, DetailView): model = Team + def dispatch(self, request, *args, **kwargs): + user = request.user + if user.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: + return super().dispatch(request, *args, **kwargs) + raise PermissionDenied + class TeamUpdateView(LoginRequiredMixin, UpdateView): model = Team form_class = TeamForm template_name = "participation/update_team.html" + def dispatch(self, request, *args, **kwargs): + user = request.user + if user.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: + return super().dispatch(request, *args, **kwargs) + raise PermissionDenied + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["participation_form"] = ParticipationForm(data=self.request.POST or None, @@ -115,11 +131,24 @@ class MyParticipationDetailView(LoginRequiredMixin, RedirectView): class ParticipationDetailView(LoginRequiredMixin, DetailView): model = Participation + def dispatch(self, request, *args, **kwargs): + user = request.user + if user.is_admin or user.registration.participates and user.registration.team.participation.pk == kwargs["pk"]: + return super().dispatch(request, *args, **kwargs) + raise PermissionDenied + class UploadVideoView(LoginRequiredMixin, UpdateView): model = Video form_class = UploadVideoForm template_name = "participation/upload_video.html" + def dispatch(self, request, *args, **kwargs): + user = request.user + if user.is_admin or user.registration.participates\ + and user.registration.team.participation.pk == self.object.participation.pk: + return super().dispatch(request, *args, **kwargs) + raise PermissionDenied + def get_success_url(self): return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,)) diff --git a/apps/registration/models.py b/apps/registration/models.py index f7abe84..5c3535a 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -59,6 +59,10 @@ class Registration(PolymorphicModel): def participates(self): return isinstance(self, StudentRegistration) or isinstance(self, CoachRegistration) + @property + def is_admin(self): + return isinstance(self, AdminRegistration) or self.user.is_superuser + def __str__(self): return f"{self.user.first_name} {self.user.last_name}" diff --git a/apps/registration/templates/registration/user_detail.html b/apps/registration/templates/registration/user_detail.html index 9ed7bb3..38c5519 100644 --- a/apps/registration/templates/registration/user_detail.html +++ b/apps/registration/templates/registration/user_detail.html @@ -21,6 +21,16 @@
{{ user_object.email }} {% if not user_object.registration.email_confirmed %} ({% trans "Not confirmed" %}, {% trans "resend the validation link" %}){% endif %}
+ {% if user_object.registration.participates or True %} +
{% trans "Team:" %}
+ {% trans "any" as any %} +
+ + {{ user_object.registration.team|default:any }} + +
+ {% endif %} + {% if user_object.registration.studentregistration %}
{% trans "Student class:" %}
{{ user_object.registration.get_student_class_display }}
@@ -32,7 +42,10 @@
{% if user_object.registration.photo_authorization %} {% trans "Download" %} - {% endif %} + {% endif %} + {% if user_object.pk == user.pk %} + + {% endif %}
{% elif user_object.registration.coachregistration %}
{% trans "Profesional activity:" %}
@@ -46,9 +59,11 @@
{{ user_object.registration.give_contact_to_animath|yesno }}
- + {% if user.pk == user_object.pk or user.registration.is_admin %} + + {% endif %} {% trans "Update user" as modal_title %} diff --git a/apps/registration/views.py b/apps/registration/views.py index 0b8a2d6..7b4819a 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -4,7 +4,7 @@ from corres2math.tokens import email_validation_token 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.core.exceptions import ValidationError, PermissionDenied from django.db import transaction from django.http import FileResponse, Http404 from django.shortcuts import redirect, resolve_url @@ -135,12 +135,24 @@ class UserDetailView(LoginRequiredMixin, DetailView): context_object_name = "user_object" template_name = "registration/user_detail.html" + def dispatch(self, request, *args, **kwargs): + user = request.user + if not user.registration.is_admin and user.pk != kwargs["pk"]: + raise PermissionDenied + return super().dispatch(request, *args, **kwargs) + class UserUpdateView(LoginRequiredMixin, UpdateView): model = User form_class = UserForm template_name = "registration/update_user.html" + def dispatch(self, request, *args, **kwargs): + user = request.user + if not user.registration.is_admin and user.pk != kwargs["pk"]: + raise PermissionDenied + return super().dispatch(request, *args, **kwargs) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) user = self.get_object() @@ -168,6 +180,12 @@ class UserUploadPhotoAuthorizationView(LoginRequiredMixin, UpdateView): form_class = PhotoAuthorizationForm template_name = "registration/upload_photo_authorization.html" + def dispatch(self, request, *args, **kwargs): + user = request.user + if not user.registration.is_admin and user.registration.pk != kwargs["pk"]: + raise PermissionDenied + return super().dispatch(request, *args, **kwargs) + @transaction.atomic def form_valid(self, form): old_instance = StudentRegistration.objects.get(pk=self.object.pk) @@ -186,6 +204,9 @@ class PhotoAuthorizationView(LoginRequiredMixin, View): if not os.path.exists(path): raise Http404 student = StudentRegistration.objects.get(photo_authorization__endswith=filename) + user = request.user + if not user.registration.is_admin and user.pk != student.user.pk: + raise PermissionDenied mime = Magic(mime=True) mime_type = mime.from_file(path) ext = mime_type.split("/")[1].replace("jpeg", "jpg") diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 39c561a..9e1cf6d 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-09-27 14:31+0200\n" +"POT-Creation-Date: 2020-09-27 16:10+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -141,7 +141,7 @@ msgid "Team {name} ({trigram})" msgstr "Équipe {name} ({trigram})" #: apps/participation/models.py:48 apps/participation/models.py:59 -#: apps/registration/models.py:81 apps/registration/models.py:127 +#: apps/registration/models.py:85 apps/registration/models.py:131 msgid "team" msgstr "équipe" @@ -225,42 +225,40 @@ msgstr "Rejoindre" #: apps/participation/templates/participation/participation_detail.html:6 #: apps/participation/templates/participation/team_detail.html:6 #: apps/registration/templates/registration/user_detail.html:6 +#: apps/registration/templates/registration/user_detail.html:26 msgid "any" msgstr "aucun" -#: apps/participation/templates/participation/participation_detail.html:11 -#: apps/participation/templates/participation/participation_detail.html:27 -#, fuzzy -#| msgid "participation" +#: apps/participation/templates/participation/participation_detail.html:9 msgid "Participation of team" -msgstr "participation" +msgstr "Participation de l'équipe" -#: apps/participation/templates/participation/participation_detail.html:15 +#: apps/participation/templates/participation/participation_detail.html:13 #: apps/participation/templates/participation/team_detail.html:29 msgid "Chosen problem:" msgstr "Problème choisi :" -#: apps/participation/templates/participation/participation_detail.html:30 +#: apps/participation/templates/participation/participation_detail.html:19 msgid "No video sent" msgstr "Pas de vidéo envoyée" -#: apps/participation/templates/participation/participation_detail.html:31 +#: apps/participation/templates/participation/participation_detail.html:20 msgid "Video link:" msgstr "Lien de la vidéo :" -#: apps/participation/templates/participation/participation_detail.html:32 -#: apps/participation/templates/participation/participation_detail.html:46 +#: apps/participation/templates/participation/participation_detail.html:23 +#: apps/participation/templates/participation/participation_detail.html:38 #: apps/participation/templates/participation/upload_video.html:11 #: apps/registration/templates/registration/upload_photo_authorization.html:18 -#: apps/registration/templates/registration/user_detail.html:60 +#: apps/registration/templates/registration/user_detail.html:72 msgid "Upload" msgstr "Téléverser" -#: apps/participation/templates/participation/participation_detail.html:37 +#: apps/participation/templates/participation/participation_detail.html:30 msgid "This video platform is not supported yet." msgstr "La plateforme de cette vidéo n'est pas encore supportée." -#: apps/participation/templates/participation/participation_detail.html:45 +#: apps/participation/templates/participation/participation_detail.html:37 msgid "Upload video" msgstr "Envoyer la vidéo" @@ -300,8 +298,8 @@ msgstr "Pas encore envoyée" #: apps/participation/templates/participation/team_detail.html:53 #: apps/participation/templates/participation/update_team.html:12 #: apps/registration/templates/registration/update_user.html:12 -#: apps/registration/templates/registration/user_detail.html:50 -#: apps/registration/templates/registration/user_detail.html:55 +#: apps/registration/templates/registration/user_detail.html:61 +#: apps/registration/templates/registration/user_detail.html:67 msgid "Update" msgstr "Modifier" @@ -343,7 +341,7 @@ msgstr "rôle" msgid "participant" msgstr "participant" -#: apps/registration/forms.py:16 apps/registration/models.py:136 +#: apps/registration/forms.py:16 apps/registration/models.py:140 msgid "coach" msgstr "encadrant" @@ -364,75 +362,75 @@ msgstr "email confirmé" msgid "Activate your Correspondances account" msgstr "Activez votre compte des Correspondances" -#: apps/registration/models.py:66 +#: apps/registration/models.py:70 msgid "registration" msgstr "inscription" -#: apps/registration/models.py:67 +#: apps/registration/models.py:71 msgid "registrations" msgstr "inscriptions" -#: apps/registration/models.py:86 +#: apps/registration/models.py:90 msgid "12th grade" msgstr "Terminale" -#: apps/registration/models.py:87 +#: apps/registration/models.py:91 msgid "11th grade" msgstr "Première" -#: apps/registration/models.py:88 +#: apps/registration/models.py:92 msgid "10th grade or lower" msgstr "Seconde ou inférieur" -#: apps/registration/models.py:90 +#: apps/registration/models.py:94 msgid "student class" msgstr "classe" -#: apps/registration/models.py:95 +#: apps/registration/models.py:99 msgid "school" msgstr "école" -#: apps/registration/models.py:100 +#: apps/registration/models.py:104 msgid "photo authorization" msgstr "autorisation de droit à l'image" -#: apps/registration/models.py:108 +#: apps/registration/models.py:112 msgid "student" msgstr "étudiant" -#: apps/registration/models.py:116 +#: apps/registration/models.py:120 msgid "student registration" msgstr "inscription d'élève" -#: apps/registration/models.py:117 +#: apps/registration/models.py:121 msgid "student registrations" msgstr "inscriptions d'élève" -#: apps/registration/models.py:131 +#: apps/registration/models.py:135 msgid "professional activity" msgstr "activité professionnelle" -#: apps/registration/models.py:144 +#: apps/registration/models.py:148 msgid "coach registration" msgstr "inscription d'encadrant" -#: apps/registration/models.py:145 +#: apps/registration/models.py:149 msgid "coach registrations" msgstr "inscriptions d'encadrants" -#: apps/registration/models.py:150 +#: apps/registration/models.py:154 msgid "role of the administrator" msgstr "rôle de l'administrateur" -#: apps/registration/models.py:155 +#: apps/registration/models.py:159 msgid "admin" msgstr "admin" -#: apps/registration/models.py:163 +#: apps/registration/models.py:167 msgid "admin registration" msgstr "inscription d'administrateur" -#: apps/registration/models.py:164 +#: apps/registration/models.py:168 msgid "admin registrations" msgstr "inscriptions d'administrateur" @@ -624,42 +622,46 @@ msgid "resend the validation link" msgstr "Renvoyer le lien de validation" #: apps/registration/templates/registration/user_detail.html:25 +msgid "Team:" +msgstr "Équipe :" + +#: apps/registration/templates/registration/user_detail.html:35 msgid "Student class:" msgstr "Classe :" -#: apps/registration/templates/registration/user_detail.html:28 +#: apps/registration/templates/registration/user_detail.html:38 msgid "School:" msgstr "École :" -#: apps/registration/templates/registration/user_detail.html:31 +#: apps/registration/templates/registration/user_detail.html:41 msgid "Photo authorization:" msgstr "Autorisation de droit à l'image" -#: apps/registration/templates/registration/user_detail.html:34 +#: apps/registration/templates/registration/user_detail.html:44 msgid "Download" msgstr "Télécharger" -#: apps/registration/templates/registration/user_detail.html:35 +#: apps/registration/templates/registration/user_detail.html:45 msgid "Replace" msgstr "Remplacer" -#: apps/registration/templates/registration/user_detail.html:38 +#: apps/registration/templates/registration/user_detail.html:48 msgid "Profesional activity:" msgstr "Activité professionnelle :" -#: apps/registration/templates/registration/user_detail.html:41 +#: apps/registration/templates/registration/user_detail.html:51 msgid "Role:" msgstr "Rôle :" -#: apps/registration/templates/registration/user_detail.html:45 +#: apps/registration/templates/registration/user_detail.html:55 msgid "Grant Animath to contact me in the future about other actions:" msgstr "Autorise Animath à recontacter à propos d'autres actions :" -#: apps/registration/templates/registration/user_detail.html:54 +#: apps/registration/templates/registration/user_detail.html:66 msgid "Update user" msgstr "Modifier l'utilisateur" -#: apps/registration/templates/registration/user_detail.html:59 +#: apps/registration/templates/registration/user_detail.html:71 msgid "Upload photo authorization" msgstr "Téléverser l'autorisation de droit à l'image" @@ -683,7 +685,7 @@ msgstr "Mail de confirmation de l'adresse mail envoyé" msgid "Resend email validation link" msgstr "Renvoyé le lien de validation de l'adresse mail" -#: apps/registration/views.py:192 +#: apps/registration/views.py:198 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}"