Protect pages (not tested)

This commit is contained in:
Yohann D'ANELLO 2021-01-17 12:40:23 +01:00
parent 1e413229a1
commit c151ff3611
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
7 changed files with 207 additions and 37 deletions

View File

@ -21,7 +21,7 @@ from magic import Magic
from registration.models import AdminRegistration from registration.models import AdminRegistration
from tfjm.lists import get_sympa_client from tfjm.lists import get_sympa_client
from tfjm.matrix import Matrix from tfjm.matrix import Matrix
from tfjm.views import AdminMixin from tfjm.views import AdminMixin, VolunteerMixin
from .forms import JoinTeamForm, NoteForm, ParticipationForm, PassageForm, PoolForm, PoolTeamsForm, \ from .forms import JoinTeamForm, NoteForm, ParticipationForm, PassageForm, PoolForm, PoolTeamsForm, \
RequestValidationForm, TeamForm, TournamentForm, ValidateParticipationForm, SolutionForm, SynthesisForm RequestValidationForm, TeamForm, TournamentForm, ValidateParticipationForm, SolutionForm, SynthesisForm
@ -156,9 +156,11 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
user = request.user user = request.user
self.object = self.get_object() self.object = self.get_object()
# Ensure that the user is an admin or a member of the team # Ensure that the user is an admin or a volunteer or a member of the team
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.pk == kwargs["pk"]: user.registration.team and user.registration.team.pk == kwargs["pk"] \
or user.registration.is_volunteer \
and self.object.participation.tournament in user.registration.interesting_tournaments:
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
raise PermissionDenied raise PermissionDenied
@ -270,8 +272,9 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView):
if not user.is_authenticated: if not user.is_authenticated:
return super().handle_no_permission() 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"]: or user.registration.is_volunteer \
and self.object.participation.tournament in user.registration.interesting_tournaments:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
raise PermissionDenied raise PermissionDenied
@ -302,7 +305,9 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
user = request.user user = request.user
if not user.is_authenticated: if not user.is_authenticated:
return super().handle_no_permission() 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"] \
or user.registration.is_volunteer \
and self.object.participation.tournament in user.registration.interesting_tournaments:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
raise PermissionDenied raise PermissionDenied
@ -386,7 +391,9 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView):
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 \
and user.registration.team.participation \ and user.registration.team.participation \
and user.registration.team.participation.pk == kwargs["pk"]: and user.registration.team.participation.pk == kwargs["pk"] \
or user.registration.is_volunteer \
and self.object.tournament in user.registration.interesting_tournaments:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
raise PermissionDenied raise PermissionDenied
@ -417,13 +424,20 @@ class TournamentCreateView(AdminMixin, CreateView):
return reverse_lazy("participation:tournament_detail", args=(self.object.pk,)) return reverse_lazy("participation:tournament_detail", args=(self.object.pk,))
class TournamentUpdateView(AdminMixin, UpdateView): class TournamentUpdateView(VolunteerMixin, UpdateView):
""" """
Update tournament detail. Update tournament detail.
""" """
model = Tournament model = Tournament
form_class = TournamentForm form_class = TournamentForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not self.request.user.registration.is_admin \
and not (self.request.user.registration.is_volunteer
and self.request.user.registration.organized_tournaments.all()):
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
class TournamentDetailView(DetailView): class TournamentDetailView(DetailView):
""" """
@ -454,6 +468,10 @@ class SolutionUploadView(LoginRequiredMixin, FormView):
if not qs.exists(): if not qs.exists():
raise Http404 raise Http404
self.participation = qs.get() self.participation = qs.get()
if not self.request.user.is_authenticated or not self.request.user.registration.is_admin \
and not (self.request.user.registration.participates
and self.request.user.registration.team == self.participation.team):
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def form_valid(self, form): def form_valid(self, form):
@ -486,6 +504,17 @@ class PoolCreateView(AdminMixin, CreateView):
class PoolDetailView(LoginRequiredMixin, DetailView): class PoolDetailView(LoginRequiredMixin, DetailView):
model = Pool model = Pool
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.participates \
and request.user.registration.team \
and request.user.registration.team.participation in self.get_object().participations.all() \
or request.user.registration.is_volunteer \
and self.get_object().tournament in request.user.registration.interesting_tournaments:
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -499,26 +528,53 @@ class PoolDetailView(LoginRequiredMixin, DetailView):
return context return context
class PoolUpdateView(AdminMixin, UpdateView): class PoolUpdateView(VolunteerMixin, UpdateView):
model = Pool model = Pool
form_class = PoolForm form_class = PoolForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and (self.get_object().tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.get_object().juries.all()):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
class PoolUpdateTeamsView(AdminMixin, UpdateView):
class PoolUpdateTeamsView(VolunteerMixin, UpdateView):
model = Pool model = Pool
form_class = PoolTeamsForm form_class = PoolTeamsForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and (self.get_object().tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.get_object().juries.all()):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
class PassageCreateView(AdminMixin, CreateView):
class PassageCreateView(VolunteerMixin, CreateView):
model = Passage model = Passage
form_class = PassageForm form_class = PassageForm
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
qs = Pool.objects.filter(pk=self.kwargs["pk"]) qs = Pool.objects.filter(pk=self.kwargs["pk"])
if not qs.exists(): if not qs.exists():
raise Http404 raise Http404
self.pool = qs.get() self.pool = qs.get()
return super().dispatch(request, *args, **kwargs)
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and (self.pool.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.pool.juries.all()):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get_form(self, form_class=None): def get_form(self, form_class=None):
form = super().get_form(form_class) form = super().get_form(form_class)
@ -532,6 +588,19 @@ class PassageCreateView(AdminMixin, CreateView):
class PassageDetailView(LoginRequiredMixin, DetailView): class PassageDetailView(LoginRequiredMixin, DetailView):
model = Passage model = Passage
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and (self.get_object().pool.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.get_object().pool.juries.all()) \
or request.user.registration.participates and request.user.registration.team \
and request.user.registration.team.participation in [self.get_object().defender,
self.get_object().opponent,
self.get_object().reporter]:
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
if self.request.user.registration in self.object.pool.juries.all(): if self.request.user.registration in self.object.pool.juries.all():
@ -540,21 +609,39 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
return context return context
class PassageUpdateView(AdminMixin, UpdateView): class PassageUpdateView(VolunteerMixin, UpdateView):
model = Passage model = Passage
form_class = PassageForm form_class = PassageForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and (self.get_object().pool.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.get_object().pool.juries.all()):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
class SynthesisUploadView(LoginRequiredMixin, FormView): class SynthesisUploadView(LoginRequiredMixin, FormView):
template_name = "participation/upload_synthesis.html" template_name = "participation/upload_synthesis.html"
form_class = SynthesisForm form_class = SynthesisForm
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.registration.participates:
return self.handle_no_permission()
qs = Passage.objects.filter(pk=self.kwargs["pk"]) qs = Passage.objects.filter(pk=self.kwargs["pk"])
if not qs.exists(): if not qs.exists():
raise Http404 raise Http404
self.participation = self.request.user.registration.team.participation self.participation = self.request.user.registration.team.participation
self.passage = qs.get() self.passage = qs.get()
if self.participation not in [self.passage.defender, self.passage.opponent, self.passage.reporter]:
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def form_valid(self, form): def form_valid(self, form):
@ -579,6 +666,16 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
return reverse_lazy("participation:passage_detail", args=(self.passage.pk,)) return reverse_lazy("participation:passage_detail", args=(self.passage.pk,))
class NoteUpdateView(LoginRequiredMixin, UpdateView): class NoteUpdateView(VolunteerMixin, UpdateView):
model = Note model = Note
form_class = NoteForm form_class = NoteForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if request.user.registration.is_admin or request.user.registration.is_volunteer \
and self.get_object().jury == request.user.registration:
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()

View File

@ -55,6 +55,7 @@ class AddOrganizerForm(forms.ModelForm):
("volunteer", _("volunteer").capitalize()), ("volunteer", _("volunteer").capitalize()),
("admin", _("admin").capitalize()), ("admin", _("admin").capitalize()),
], ],
initial="volunteer",
) )
def clean_email(self): def clean_email(self):

View File

@ -81,6 +81,10 @@ class Registration(PolymorphicModel):
def is_admin(self): def is_admin(self):
return isinstance(self, AdminRegistration) or self.user.is_superuser return isinstance(self, AdminRegistration) or self.user.is_superuser
@property
def is_volunteer(self):
return isinstance(self, VolunteerRegistration)
@property @property
def matrix_username(self): def matrix_username(self):
return f"tfjm_{self.user.pk}" return f"tfjm_{self.user.pk}"
@ -249,6 +253,10 @@ class VolunteerRegistration(Registration):
verbose_name=_("professional activity"), verbose_name=_("professional activity"),
) )
@property
def interesting_tournaments(self) -> set:
return set(self.organized_tournaments.all()).union(map(lambda pool: pool.tournament, self.jury_in.all()))
@property @property
def type(self): def type(self):
return _('volunteer') return _('volunteer')

View File

@ -30,8 +30,8 @@
{% block extrajavascript %} {% block extrajavascript %}
<script> <script>
$("#id_role").change(function() { $("#id_type").change(function() {
let selected_role = $("#id_role :selected"); let selected_role = $("#id_type :selected");
if (selected_role.val() === "volunteer") { if (selected_role.val() === "volunteer") {
$("#registration_form").html($("#volunteer_registration_form").html()); $("#registration_form").html($("#volunteer_registration_form").html());
} }

View File

@ -4,9 +4,9 @@
{% block content %} {% block content %}
{% if user.registration.is_admin %} {% if user.registration.is_admin %}
<button href="{% url "registration:add_organizer" %}" class="btn btn-block btn-secondary"> <a href="{% url "registration:add_organizer" %}" class="btn btn-block btn-secondary">
<i class="fas fa-user-plus"></i> {% trans "Add organizer" %} <i class="fas fa-user-plus"></i> {% trans "Add organizer" %}
</button> </a>
<hr> <hr>
{% endif %} {% endif %}

View File

@ -8,6 +8,7 @@ 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 PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied, ValidationError
from django.db import transaction from django.db import transaction
from django.db.models import Q
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
from django.urls import reverse_lazy from django.urls import reverse_lazy
@ -17,9 +18,9 @@ from django.views.generic import CreateView, DetailView, RedirectView, TemplateV
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from magic import Magic from magic import Magic
from participation.models import Solution, Synthesis from participation.models import Solution, Synthesis, Passage
from tfjm.tokens import email_validation_token from tfjm.tokens import email_validation_token
from tfjm.views import AdminMixin, UserMixin from tfjm.views import AdminMixin, UserMixin, VolunteerMixin
from .forms import AddOrganizerForm, AdminRegistrationForm, CoachRegistrationForm, HealthSheetForm, \ from .forms import AddOrganizerForm, AdminRegistrationForm, CoachRegistrationForm, HealthSheetForm, \
ParentalAuthorizationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \ ParentalAuthorizationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \
@ -67,6 +68,7 @@ class SignupView(CreateView):
registration = registration_form.instance registration = registration_form.instance
registration.user = form.instance registration.user = form.instance
registration.save() registration.save()
registration.send_email_validation_link()
return ret return ret
@ -74,7 +76,7 @@ class SignupView(CreateView):
return reverse_lazy("registration:email_validation_sent") return reverse_lazy("registration:email_validation_sent")
class AddOrganizerView(AdminMixin, CreateView): class AddOrganizerView(VolunteerMixin, CreateView):
model = User model = User
form_class = AddOrganizerForm form_class = AddOrganizerForm
template_name = "registration/add_organizer.html" template_name = "registration/add_organizer.html"
@ -89,6 +91,10 @@ class AddOrganizerView(AdminMixin, CreateView):
del context["volunteer_registration_form"].fields["email_confirmed"] del context["volunteer_registration_form"].fields["email_confirmed"]
del context["admin_registration_form"].fields["email_confirmed"] del context["admin_registration_form"].fields["email_confirmed"]
if not self.request.user.registration.is_admin:
del context["form"].fields["type"]
del context["admin_registration_form"]
return context return context
@transaction.atomic @transaction.atomic
@ -107,6 +113,7 @@ class AddOrganizerView(AdminMixin, CreateView):
registration = registration_form.instance registration = registration_form.instance
registration.user = form.instance registration.user = form.instance
registration.save() registration.save()
registration.send_email_validation_link()
return ret return ret
@ -114,7 +121,6 @@ class AddOrganizerView(AdminMixin, CreateView):
return reverse_lazy("registration:email_validation_sent") return reverse_lazy("registration:email_validation_sent")
class UserValidateView(TemplateView): class UserValidateView(TemplateView):
""" """
A view to validate the email address. A view to validate the email address.
@ -204,6 +210,19 @@ class UserDetailView(UserMixin, 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):
me = request.user
if not me.is_authenticated:
return self.handle_no_permission()
user = self.get_object()
if user == me or me.registration.is_admin or me.registration.is_volunteer \
and user.registration.participates and user.registration.team \
and user.registration.team.participation.tournament in user.registration.organized_tournaments.all() \
or user.registration.is_volunteer and me.registration.is_volunteer \
and me.registration.interesting_tournaments.intersection(user.registration.intersting_tournaments):
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["title"] = _("Detail of user {user}").format(user=str(self.object.registration)) context["title"] = _("Detail of user {user}").format(user=str(self.object.registration))
@ -227,6 +246,12 @@ class UserUpdateView(UserMixin, UpdateView):
form_class = UserForm form_class = UserForm
template_name = "registration/update_user.html" template_name = "registration/update_user.html"
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated or \
not self.request.user.registration.is_admin and self.request.user != self.get_object():
return self.handle_no_permission()
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()
@ -268,6 +293,12 @@ class UserUploadPhotoAuthorizationView(UserMixin, UpdateView):
template_name = "registration/upload_photo_authorization.html" template_name = "registration/upload_photo_authorization.html"
extra_context = dict(title=_("Upload photo authorization")) extra_context = dict(title=_("Upload photo authorization"))
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated or \
not self.request.user.registration.is_admin and self.request.user != self.get_object().user:
return self.handle_no_permission()
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)
@ -288,6 +319,12 @@ class UserUploadHealthSheetView(UserMixin, UpdateView):
template_name = "registration/upload_health_sheet.html" template_name = "registration/upload_health_sheet.html"
extra_context = dict(title=_("Upload health sheet")) extra_context = dict(title=_("Upload health sheet"))
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated or \
not self.request.user.registration.is_admin and self.request.user != self.get_object().user:
return self.handle_no_permission()
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)
@ -308,6 +345,12 @@ class UserUploadParentalAuthorizationView(UserMixin, UpdateView):
template_name = "registration/upload_parental_authorization.html" template_name = "registration/upload_parental_authorization.html"
extra_context = dict(title=_("Upload parental authorization")) extra_context = dict(title=_("Upload parental authorization"))
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated or \
not self.request.user.registration.is_admin and self.request.user != self.get_object().user:
return self.handle_no_permission()
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)
@ -330,7 +373,8 @@ class PhotoAuthorizationView(LoginRequiredMixin, View):
raise Http404 raise Http404
student = ParticipantRegistration.objects.get(photo_authorization__endswith=filename) student = ParticipantRegistration.objects.get(photo_authorization__endswith=filename)
user = request.user user = request.user
if not user.registration.is_admin and user.pk != student.user.pk: if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
and student.team.participation.tournament in user.registration.organized_tournaments.all()):
raise PermissionDenied raise PermissionDenied
# Guess mime type of the file # Guess mime type of the file
mime = Magic(mime=True) mime = Magic(mime=True)
@ -352,7 +396,8 @@ class HealthSheetView(LoginRequiredMixin, View):
raise Http404 raise Http404
student = ParticipantRegistration.objects.get(health_sheet__endswith=filename) student = ParticipantRegistration.objects.get(health_sheet__endswith=filename)
user = request.user user = request.user
if not user.registration.is_admin and user.pk != student.user.pk: if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
and student.team.participation.tournament in user.registration.organized_tournaments.all()):
raise PermissionDenied raise PermissionDenied
# Guess mime type of the file # Guess mime type of the file
mime = Magic(mime=True) mime = Magic(mime=True)
@ -374,7 +419,8 @@ class ParentalAuthorizationView(LoginRequiredMixin, View):
raise Http404 raise Http404
student = StudentRegistration.objects.get(parental_authorization__endswith=filename) student = StudentRegistration.objects.get(parental_authorization__endswith=filename)
user = request.user user = request.user
if not user.registration.is_admin and user.pk != student.user.pk: if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
and student.team.participation.tournament in user.registration.organized_tournaments.all()):
raise PermissionDenied raise PermissionDenied
# Guess mime type of the file # Guess mime type of the file
mime = Magic(mime=True) mime = Magic(mime=True)
@ -395,10 +441,19 @@ class SolutionView(LoginRequiredMixin, View):
if not os.path.exists(path): if not os.path.exists(path):
raise Http404 raise Http404
solution = Solution.objects.get(file__endswith=filename) solution = Solution.objects.get(file__endswith=filename)
# user = request.user user = request.user
# if False: if not (user.registration.is_admin or user.registration.is_volunteer
# FIXME Check ACL and Passage.objects.filter(Q(pool__juries=user.registration)
# raise PermissionDenied | Q(pool__tournament__in=user.registration.organized_tournaments.all()),
defender=solution.participation,
solution_number=solution.problem).exists()
or user.registration.participates and user.registration.team
and Passage.objects.filter(Q(defender=user.registration.team.participation)
| Q(opponent=user.registration.team.participation)
| Q(reporter=user.registration.team.participation),
defender=solution.participation,
solution_number=solution.problem).exists()):
raise PermissionDenied
# Guess mime type of the file # Guess mime type of the file
mime = Magic(mime=True) mime = Magic(mime=True)
mime_type = mime.from_file(path) mime_type = mime.from_file(path)
@ -417,17 +472,19 @@ class SynthesisView(LoginRequiredMixin, View):
path = f"media/syntheses/{filename}" path = f"media/syntheses/{filename}"
if not os.path.exists(path): if not os.path.exists(path):
raise Http404 raise Http404
solution = Synthesis.objects.get(file__endswith=filename) synthesis = Synthesis.objects.get(file__endswith=filename)
# user = request.user user = request.user
# if False: if not (user.registration.is_admin or user.registration.is_volunteer
# FIXME Check ACL and (user.registration in synthesis.passage.pool.juries.all()
# raise PermissionDenied or user.registration in synthesis.passage.pool.tournament.organizers.all())
or user.registration.participates and user.registration.team == synthesis.participation.team):
raise PermissionDenied
# Guess mime type of the file # Guess mime type of the file
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")
# Replace file name # Replace file name
true_file_name = str(solution) + f".{ext}" true_file_name = str(synthesis) + f".{ext}"
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name) return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)

View File

@ -9,7 +9,14 @@ from haystack.generic_views import SearchView
class AdminMixin(LoginRequiredMixin): class AdminMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated and not request.user.registration.is_admin: if request.user.is_authenticated and not request.user.registration.is_admin:
raise PermissionDenied self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
class VolunteerMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated and not request.user.registration.is_volunteer:
self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
@ -17,7 +24,7 @@ class UserMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
user = request.user user = request.user
if user.is_authenticated and not user.registration.is_admin and user.registration.pk != kwargs["pk"]: if user.is_authenticated and not user.registration.is_admin and user.registration.pk != kwargs["pk"]:
raise PermissionDenied self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)