From c151ff3611a4fca269d57d4909c436ca94969c09 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Sun, 17 Jan 2021 12:40:23 +0100 Subject: [PATCH] Protect pages (not tested) --- apps/participation/views.py | 125 ++++++++++++++++-- apps/registration/forms.py | 1 + apps/registration/models.py | 8 ++ .../templates/registration/add_organizer.html | 4 +- .../templates/registration/user_list.html | 4 +- apps/registration/views.py | 91 ++++++++++--- tfjm/views.py | 11 +- 7 files changed, 207 insertions(+), 37 deletions(-) diff --git a/apps/participation/views.py b/apps/participation/views.py index cc45a81..8519a89 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -21,7 +21,7 @@ from magic import Magic from registration.models import AdminRegistration from tfjm.lists import get_sympa_client 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, \ RequestValidationForm, TeamForm, TournamentForm, ValidateParticipationForm, SolutionForm, SynthesisForm @@ -156,9 +156,11 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) def get(self, request, *args, **kwargs): user = request.user 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 \ - 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) raise PermissionDenied @@ -270,8 +272,9 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView): 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"]: + 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().dispatch(request, *args, **kwargs) raise PermissionDenied @@ -302,7 +305,9 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView): 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"] \ + or user.registration.is_volunteer \ + and self.object.participation.tournament in user.registration.interesting_tournaments: return super().dispatch(request, *args, **kwargs) raise PermissionDenied @@ -386,7 +391,9 @@ class ParticipationDetailView(LoginRequiredMixin, DetailView): raise PermissionDenied(_("The team is not validated yet.")) if user.registration.is_admin or user.registration.participates \ 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) raise PermissionDenied @@ -417,13 +424,20 @@ class TournamentCreateView(AdminMixin, CreateView): return reverse_lazy("participation:tournament_detail", args=(self.object.pk,)) -class TournamentUpdateView(AdminMixin, UpdateView): +class TournamentUpdateView(VolunteerMixin, UpdateView): """ Update tournament detail. """ model = Tournament 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): """ @@ -454,6 +468,10 @@ class SolutionUploadView(LoginRequiredMixin, FormView): if not qs.exists(): raise Http404 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) def form_valid(self, form): @@ -486,6 +504,17 @@ class PoolCreateView(AdminMixin, CreateView): class PoolDetailView(LoginRequiredMixin, DetailView): 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): context = super().get_context_data(**kwargs) @@ -499,26 +528,53 @@ class PoolDetailView(LoginRequiredMixin, DetailView): return context -class PoolUpdateView(AdminMixin, UpdateView): +class PoolUpdateView(VolunteerMixin, UpdateView): model = Pool 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 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 form_class = PassageForm 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"]) if not qs.exists(): raise Http404 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): form = super().get_form(form_class) @@ -532,6 +588,19 @@ class PassageCreateView(AdminMixin, CreateView): class PassageDetailView(LoginRequiredMixin, DetailView): 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): context = super().get_context_data(**kwargs) if self.request.user.registration in self.object.pool.juries.all(): @@ -540,21 +609,39 @@ class PassageDetailView(LoginRequiredMixin, DetailView): return context -class PassageUpdateView(AdminMixin, UpdateView): +class PassageUpdateView(VolunteerMixin, UpdateView): model = Passage 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): template_name = "participation/upload_synthesis.html" form_class = SynthesisForm 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"]) if not qs.exists(): raise Http404 self.participation = self.request.user.registration.team.participation 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) def form_valid(self, form): @@ -579,6 +666,16 @@ class SynthesisUploadView(LoginRequiredMixin, FormView): return reverse_lazy("participation:passage_detail", args=(self.passage.pk,)) -class NoteUpdateView(LoginRequiredMixin, UpdateView): +class NoteUpdateView(VolunteerMixin, UpdateView): model = Note 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() diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 89b8d86..ad28483 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -55,6 +55,7 @@ class AddOrganizerForm(forms.ModelForm): ("volunteer", _("volunteer").capitalize()), ("admin", _("admin").capitalize()), ], + initial="volunteer", ) def clean_email(self): diff --git a/apps/registration/models.py b/apps/registration/models.py index 532538e..0e28559 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -81,6 +81,10 @@ class Registration(PolymorphicModel): def is_admin(self): return isinstance(self, AdminRegistration) or self.user.is_superuser + @property + def is_volunteer(self): + return isinstance(self, VolunteerRegistration) + @property def matrix_username(self): return f"tfjm_{self.user.pk}" @@ -249,6 +253,10 @@ class VolunteerRegistration(Registration): 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 def type(self): return _('volunteer') diff --git a/apps/registration/templates/registration/add_organizer.html b/apps/registration/templates/registration/add_organizer.html index a61974f..aee2ffd 100644 --- a/apps/registration/templates/registration/add_organizer.html +++ b/apps/registration/templates/registration/add_organizer.html @@ -30,8 +30,8 @@ {% block extrajavascript %}