Protect some pages

This commit is contained in:
Yohann D'ANELLO 2020-09-27 16:35:31 +02:00
parent 56193dbecf
commit 88c4a6b218
5 changed files with 136 additions and 65 deletions

View File

@ -15,18 +15,20 @@ class CreateTeamView(LoginRequiredMixin, CreateView):
extra_context = dict(title=_("Create team")) extra_context = dict(title=_("Create team"))
template_name = "participation/create_team.html" template_name = "participation/create_team.html"
@transaction.atomic def dispatch(self, request, *args, **kwargs):
def form_valid(self, form): user = request.user
user = self.request.user
registration = user.registration registration = user.registration
if not registration.participates: if not registration.participates:
form.add_error(None, _("You don't participate, so you can't create a team.")) raise PermissionDenied(_("You don't participate, so you can't create a team."))
return self.form_invalid(form)
elif registration.team: elif registration.team:
form.add_error(None, _("You are already in a team.")) raise PermissionDenied(_("You are already in a team."))
return self.form_invalid(form) return super().dispatch(request, *args, **kwargs)
@transaction.atomic
def form_valid(self, form):
ret = super().form_valid(form) ret = super().form_valid(form)
user = self.request.user
registration = user.registration
registration.team = form.instance registration.team = form.instance
registration.save() registration.save()
return ret return ret
@ -41,19 +43,21 @@ class JoinTeamView(LoginRequiredMixin, FormView):
extra_context = dict(title=_("Join team")) extra_context = dict(title=_("Join team"))
template_name = "participation/create_team.html" template_name = "participation/create_team.html"
@transaction.atomic def dispatch(self, request, *args, **kwargs):
def form_valid(self, form): user = request.user
user = self.request.user
registration = user.registration registration = user.registration
if not registration.participates: if not registration.participates:
form.add_error(None, _("You don't participate, so you can't create a team.")) raise PermissionDenied(_("You don't participate, so you can't create a team."))
return self.form_invalid(form)
elif registration.team: elif registration.team:
form.add_error(None, _("You are already in a team.")) raise PermissionDenied(_("You are already in a team."))
return self.form_invalid(form) return super().dispatch(request, *args, **kwargs)
@transaction.atomic
def form_valid(self, form):
self.object = form.instance self.object = form.instance
ret = super().form_valid(form) ret = super().form_valid(form)
user = self.request.user
registration = user.registration
registration.team = form.instance registration.team = form.instance
registration.save() registration.save()
return ret return ret
@ -76,12 +80,24 @@ class MyTeamDetailView(LoginRequiredMixin, RedirectView):
class TeamDetailView(LoginRequiredMixin, DetailView): class TeamDetailView(LoginRequiredMixin, DetailView):
model = Team 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): class TeamUpdateView(LoginRequiredMixin, UpdateView):
model = Team model = Team
form_class = TeamForm form_class = TeamForm
template_name = "participation/update_team.html" 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): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["participation_form"] = ParticipationForm(data=self.request.POST or None, context["participation_form"] = ParticipationForm(data=self.request.POST or None,
@ -115,11 +131,24 @@ class MyParticipationDetailView(LoginRequiredMixin, RedirectView):
class ParticipationDetailView(LoginRequiredMixin, DetailView): class ParticipationDetailView(LoginRequiredMixin, DetailView):
model = Participation 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): class UploadVideoView(LoginRequiredMixin, UpdateView):
model = Video model = Video
form_class = UploadVideoForm form_class = UploadVideoForm
template_name = "participation/upload_video.html" 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): def get_success_url(self):
return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,)) return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,))

View File

@ -59,6 +59,10 @@ class Registration(PolymorphicModel):
def participates(self): def participates(self):
return isinstance(self, StudentRegistration) or isinstance(self, CoachRegistration) 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): def __str__(self):
return f"{self.user.first_name} {self.user.last_name}" return f"{self.user.first_name} {self.user.last_name}"

View File

@ -21,6 +21,16 @@
<dd class="col-sm-6"><a href="mailto:{{ user_object.email }}">{{ user_object.email }}</a> <dd class="col-sm-6"><a href="mailto:{{ user_object.email }}">{{ user_object.email }}</a>
{% if not user_object.registration.email_confirmed %} (<em>{% trans "Not confirmed" %}, <a href="{% url "registration:email_validation_resend" pk=user_object.pk %}">{% trans "resend the validation link" %}</a></em>){% endif %}</dd> {% if not user_object.registration.email_confirmed %} (<em>{% trans "Not confirmed" %}, <a href="{% url "registration:email_validation_resend" pk=user_object.pk %}">{% trans "resend the validation link" %}</a></em>){% endif %}</dd>
{% if user_object.registration.participates or True %}
<dt class="col-sm-6 text-right">{% trans "Team:" %}</dt>
{% trans "any" as any %}
<dd class="col-sm-6">
<a href="{% if user_object.registration.team %}{% url "participation:team_detail" pk=user_object.registration.team.pk %}{% else %}#{% endif %}">
{{ user_object.registration.team|default:any }}
</a>
</dd>
{% endif %}
{% if user_object.registration.studentregistration %} {% if user_object.registration.studentregistration %}
<dt class="col-sm-6 text-right">{% trans "Student class:" %}</dt> <dt class="col-sm-6 text-right">{% trans "Student class:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.get_student_class_display }}</dd> <dd class="col-sm-6">{{ user_object.registration.get_student_class_display }}</dd>
@ -32,7 +42,10 @@
<dd class="col-sm-6"> <dd class="col-sm-6">
{% if user_object.registration.photo_authorization %} {% if user_object.registration.photo_authorization %}
<a href="{{ user_object.registration.photo_authorization.url }}" data-turbolinks="false">{% trans "Download" %}</a> <a href="{{ user_object.registration.photo_authorization.url }}" data-turbolinks="false">{% trans "Download" %}</a>
{% endif %} <button class="btn btn-primary" data-toggle="modal" data-target="#uploadPhotoAuthorizationModal">{% trans "Replace" %}</button> {% endif %}
{% if user_object.pk == user.pk %}
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadPhotoAuthorizationModal">{% trans "Replace" %}</button>
{% endif %}
</dd> </dd>
{% elif user_object.registration.coachregistration %} {% elif user_object.registration.coachregistration %}
<dt class="col-sm-6 text-right">{% trans "Profesional activity:" %}</dt> <dt class="col-sm-6 text-right">{% trans "Profesional activity:" %}</dt>
@ -46,9 +59,11 @@
<dd class="col-sm-6">{{ user_object.registration.give_contact_to_animath|yesno }}</dd> <dd class="col-sm-6">{{ user_object.registration.give_contact_to_animath|yesno }}</dd>
</dl> </dl>
</div> </div>
<div class="card-footer text-center"> {% if user.pk == user_object.pk or user.registration.is_admin %}
<button class="btn btn-primary" data-toggle="modal" data-target="#updateUserModal">{% trans "Update" %}</button> <div class="card-footer text-center">
</div> <button class="btn btn-primary" data-toggle="modal" data-target="#updateUserModal">{% trans "Update" %}</button>
</div>
{% endif %}
</div> </div>
{% trans "Update user" as modal_title %} {% trans "Update user" as modal_title %}

View File

@ -4,7 +4,7 @@ from corres2math.tokens import email_validation_token
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User 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.db import transaction
from django.http import FileResponse, Http404 from django.http import FileResponse, Http404
from django.shortcuts import redirect, resolve_url from django.shortcuts import redirect, resolve_url
@ -135,12 +135,24 @@ class UserDetailView(LoginRequiredMixin, DetailView):
context_object_name = "user_object" context_object_name = "user_object"
template_name = "registration/user_detail.html" 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): class UserUpdateView(LoginRequiredMixin, UpdateView):
model = User model = User
form_class = UserForm form_class = UserForm
template_name = "registration/update_user.html" 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): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
user = self.get_object() user = self.get_object()
@ -168,6 +180,12 @@ class UserUploadPhotoAuthorizationView(LoginRequiredMixin, UpdateView):
form_class = PhotoAuthorizationForm form_class = PhotoAuthorizationForm
template_name = "registration/upload_photo_authorization.html" 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 @transaction.atomic
def form_valid(self, form): def form_valid(self, form):
old_instance = StudentRegistration.objects.get(pk=self.object.pk) old_instance = StudentRegistration.objects.get(pk=self.object.pk)
@ -186,6 +204,9 @@ class PhotoAuthorizationView(LoginRequiredMixin, View):
if not os.path.exists(path): if not os.path.exists(path):
raise Http404 raise Http404
student = StudentRegistration.objects.get(photo_authorization__endswith=filename) 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 = Magic(mime=True)
mime_type = mime.from_file(path) mime_type = mime.from_file(path)
ext = mime_type.split("/")[1].replace("jpeg", "jpg") ext = mime_type.split("/")[1].replace("jpeg", "jpg")

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-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" "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"
@ -141,7 +141,7 @@ msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})" msgstr "Équipe {name} ({trigram})"
#: apps/participation/models.py:48 apps/participation/models.py:59 #: 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" msgid "team"
msgstr "équipe" msgstr "équipe"
@ -225,42 +225,40 @@ msgstr "Rejoindre"
#: apps/participation/templates/participation/participation_detail.html:6 #: apps/participation/templates/participation/participation_detail.html:6
#: apps/participation/templates/participation/team_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:6
#: apps/registration/templates/registration/user_detail.html:26
msgid "any" msgid "any"
msgstr "aucun" msgstr "aucun"
#: apps/participation/templates/participation/participation_detail.html:11 #: apps/participation/templates/participation/participation_detail.html:9
#: apps/participation/templates/participation/participation_detail.html:27
#, fuzzy
#| msgid "participation"
msgid "Participation of team" 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 #: apps/participation/templates/participation/team_detail.html:29
msgid "Chosen problem:" msgid "Chosen problem:"
msgstr "Problème choisi :" msgstr "Problème choisi :"
#: apps/participation/templates/participation/participation_detail.html:30 #: apps/participation/templates/participation/participation_detail.html:19
msgid "No video sent" msgid "No video sent"
msgstr "Pas de vidéo envoyée" 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:" msgid "Video link:"
msgstr "Lien de la vidéo :" msgstr "Lien de la vidéo :"
#: apps/participation/templates/participation/participation_detail.html:32 #: apps/participation/templates/participation/participation_detail.html:23
#: apps/participation/templates/participation/participation_detail.html:46 #: apps/participation/templates/participation/participation_detail.html:38
#: apps/participation/templates/participation/upload_video.html:11 #: apps/participation/templates/participation/upload_video.html:11
#: apps/registration/templates/registration/upload_photo_authorization.html:18 #: 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" msgid "Upload"
msgstr "Téléverser" 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." msgid "This video platform is not supported yet."
msgstr "La plateforme de cette vidéo n'est pas encore supportée." 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" msgid "Upload video"
msgstr "Envoyer la vidéo" 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/team_detail.html:53
#: apps/participation/templates/participation/update_team.html:12 #: apps/participation/templates/participation/update_team.html:12
#: apps/registration/templates/registration/update_user.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:61
#: apps/registration/templates/registration/user_detail.html:55 #: apps/registration/templates/registration/user_detail.html:67
msgid "Update" msgid "Update"
msgstr "Modifier" msgstr "Modifier"
@ -343,7 +341,7 @@ msgstr "rôle"
msgid "participant" msgid "participant"
msgstr "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" msgid "coach"
msgstr "encadrant" msgstr "encadrant"
@ -364,75 +362,75 @@ msgstr "email confirmé"
msgid "Activate your Correspondances account" msgid "Activate your Correspondances account"
msgstr "Activez votre compte des Correspondances" msgstr "Activez votre compte des Correspondances"
#: apps/registration/models.py:66 #: apps/registration/models.py:70
msgid "registration" msgid "registration"
msgstr "inscription" msgstr "inscription"
#: apps/registration/models.py:67 #: apps/registration/models.py:71
msgid "registrations" msgid "registrations"
msgstr "inscriptions" msgstr "inscriptions"
#: apps/registration/models.py:86 #: apps/registration/models.py:90
msgid "12th grade" msgid "12th grade"
msgstr "Terminale" msgstr "Terminale"
#: apps/registration/models.py:87 #: apps/registration/models.py:91
msgid "11th grade" msgid "11th grade"
msgstr "Première" msgstr "Première"
#: apps/registration/models.py:88 #: apps/registration/models.py:92
msgid "10th grade or lower" msgid "10th grade or lower"
msgstr "Seconde ou inférieur" msgstr "Seconde ou inférieur"
#: apps/registration/models.py:90 #: apps/registration/models.py:94
msgid "student class" msgid "student class"
msgstr "classe" msgstr "classe"
#: apps/registration/models.py:95 #: apps/registration/models.py:99
msgid "school" msgid "school"
msgstr "école" msgstr "école"
#: apps/registration/models.py:100 #: apps/registration/models.py:104
msgid "photo authorization" msgid "photo authorization"
msgstr "autorisation de droit à l'image" msgstr "autorisation de droit à l'image"
#: apps/registration/models.py:108 #: apps/registration/models.py:112
msgid "student" msgid "student"
msgstr "étudiant" msgstr "étudiant"
#: apps/registration/models.py:116 #: apps/registration/models.py:120
msgid "student registration" msgid "student registration"
msgstr "inscription d'élève" msgstr "inscription d'élève"
#: apps/registration/models.py:117 #: apps/registration/models.py:121
msgid "student registrations" msgid "student registrations"
msgstr "inscriptions d'élève" msgstr "inscriptions d'élève"
#: apps/registration/models.py:131 #: apps/registration/models.py:135
msgid "professional activity" msgid "professional activity"
msgstr "activité professionnelle" msgstr "activité professionnelle"
#: apps/registration/models.py:144 #: apps/registration/models.py:148
msgid "coach registration" msgid "coach registration"
msgstr "inscription d'encadrant" msgstr "inscription d'encadrant"
#: apps/registration/models.py:145 #: apps/registration/models.py:149
msgid "coach registrations" msgid "coach registrations"
msgstr "inscriptions d'encadrants" msgstr "inscriptions d'encadrants"
#: apps/registration/models.py:150 #: apps/registration/models.py:154
msgid "role of the administrator" msgid "role of the administrator"
msgstr "rôle de l'administrateur" msgstr "rôle de l'administrateur"
#: apps/registration/models.py:155 #: apps/registration/models.py:159
msgid "admin" msgid "admin"
msgstr "admin" msgstr "admin"
#: apps/registration/models.py:163 #: apps/registration/models.py:167
msgid "admin registration" msgid "admin registration"
msgstr "inscription d'administrateur" msgstr "inscription d'administrateur"
#: apps/registration/models.py:164 #: apps/registration/models.py:168
msgid "admin registrations" msgid "admin registrations"
msgstr "inscriptions d'administrateur" msgstr "inscriptions d'administrateur"
@ -624,42 +622,46 @@ msgid "resend the validation link"
msgstr "Renvoyer le lien de validation" msgstr "Renvoyer le lien de validation"
#: apps/registration/templates/registration/user_detail.html:25 #: apps/registration/templates/registration/user_detail.html:25
msgid "Team:"
msgstr "Équipe :"
#: apps/registration/templates/registration/user_detail.html:35
msgid "Student class:" msgid "Student class:"
msgstr "Classe :" msgstr "Classe :"
#: apps/registration/templates/registration/user_detail.html:28 #: apps/registration/templates/registration/user_detail.html:38
msgid "School:" msgid "School:"
msgstr "École :" msgstr "École :"
#: apps/registration/templates/registration/user_detail.html:31 #: apps/registration/templates/registration/user_detail.html:41
msgid "Photo authorization:" msgid "Photo authorization:"
msgstr "Autorisation de droit à l'image" msgstr "Autorisation de droit à l'image"
#: apps/registration/templates/registration/user_detail.html:34 #: apps/registration/templates/registration/user_detail.html:44
msgid "Download" msgid "Download"
msgstr "Télécharger" msgstr "Télécharger"
#: apps/registration/templates/registration/user_detail.html:35 #: apps/registration/templates/registration/user_detail.html:45
msgid "Replace" msgid "Replace"
msgstr "Remplacer" msgstr "Remplacer"
#: apps/registration/templates/registration/user_detail.html:38 #: apps/registration/templates/registration/user_detail.html:48
msgid "Profesional activity:" msgid "Profesional activity:"
msgstr "Activité professionnelle :" msgstr "Activité professionnelle :"
#: apps/registration/templates/registration/user_detail.html:41 #: apps/registration/templates/registration/user_detail.html:51
msgid "Role:" msgid "Role:"
msgstr "Rôle :" 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:" msgid "Grant Animath to contact me in the future about other actions:"
msgstr "Autorise Animath à recontacter à propos d'autres 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" msgid "Update user"
msgstr "Modifier l'utilisateur" msgstr "Modifier l'utilisateur"
#: apps/registration/templates/registration/user_detail.html:59 #: apps/registration/templates/registration/user_detail.html:71
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"
@ -683,7 +685,7 @@ msgstr "Mail de confirmation de l'adresse mail envoyé"
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:192 #: apps/registration/views.py:198
#, 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}"