Update permissions for juries presidents

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-03-24 17:42:09 +01:00
parent 0b9079b431
commit d2c1a826a8
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
4 changed files with 83 additions and 38 deletions

View File

@ -178,8 +178,13 @@ class SolutionForm(forms.ModelForm):
class PoolForm(forms.ModelForm):
class Meta:
model = Pool
fields = ('tournament', 'round', 'letter', 'bbb_url', 'results_available', 'juries',)
fields = ('tournament', 'round', 'letter', 'bbb_url', 'results_available', 'jury_president', 'juries',)
widgets = {
"jury_president": forms.Select(attrs={
'class': 'selectpicker',
'data-live-search': 'true',
'data-live-search-normalize': 'true',
}),
"juries": forms.SelectMultiple(attrs={
'class': 'selectpicker',
'data-live-search': 'true',

View File

@ -816,6 +816,10 @@ class Solution(models.Model):
unique=True,
)
@property
def tournament(self):
return Tournament.final_tournament() if self.final_solution else self.participation.tournament
def __str__(self):
return _("Solution of team {team} for problem {problem}")\
.format(team=self.participation.team.name, problem=self.problem)\
@ -954,6 +958,9 @@ class Note(models.Model):
def modal_name(self):
return f"updateNotes{self.pk}"
def has_any_note(self):
return any(self.get_all())
def __str__(self):
return _("Notes of {jury} for {passage}").format(jury=self.jury, passage=self.passage)

View File

@ -721,8 +721,7 @@ class PoolUpdateView(VolunteerMixin, UpdateView):
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()):
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
@ -750,9 +749,11 @@ class PoolDownloadView(VolunteerMixin, DetailView):
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()):
reg = request.user.registration
if reg.is_admin or reg.is_volunteer \
and (self.get_object().tournament in reg.organized_tournaments.all()
or reg in self.get_object().juries.all()
or reg.pools_presided.filter(tournament=self.get_object().tournament).exists()):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
@ -785,12 +786,16 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView):
form_class = AddJuryForm
template_name = 'participation/pool_jury.html'
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():
self.object = self.get_object()
if request.user.is_authenticated and \
(request.user.registration.is_admin or request.user.registration.is_volunteer
and (self.object.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration == self.object.jury_president)):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get_context_data(self, **kwargs):
@ -866,11 +871,14 @@ class PoolRemoveJuryView(VolunteerMixin, 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.is_volunteer \
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
self.object = self.get_object()
if request.user.is_authenticated and \
(request.user.registration.is_admin or request.user.registration.is_volunteer
and (self.object.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration == self.object.jury_president)):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get(self, request, *args, **kwargs):
@ -889,11 +897,14 @@ class PoolPresideJuryView(VolunteerMixin, 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.is_volunteer \
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
self.object = self.get_object()
if request.user.is_authenticated and \
(request.user.registration.is_admin or request.user.registration.is_volunteer
and (self.object.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration == self.object.jury_president)):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def get(self, request, *args, **kwargs):
@ -919,7 +930,7 @@ class PoolUploadNotesView(VolunteerMixin, FormView, DetailView):
if request.user.is_authenticated and \
(request.user.registration.is_admin or request.user.registration.is_volunteer
and (self.object.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration in self.object.juries.all())):
or request.user.registration == self.object.jury_president)):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
@ -958,6 +969,17 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
"""
model = Pool
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
if request.user.is_authenticated and \
(request.user.registration.is_admin or request.user.registration.is_volunteer
and (self.object.tournament in request.user.registration.organized_tournaments.all()
or request.user.registration == self.object.jury_president)):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
def render_to_response(self, context, **response_kwargs): # noqa: C901
pool_size = self.object.passages.count()
passage_width = 7 if pool_size == 4 else 6
@ -1536,26 +1558,34 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
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]:
reg = request.user.registration
passage = self.get_object()
if reg.is_admin or reg.is_volunteer \
and (self.get_object().pool.tournament in reg.organized_tournaments.all()
or reg in passage.pool.juries.all()
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
or reg.participates and reg.team \
and reg.team.participation in [passage.defender, passage.opponent, passage.reporter, passage.observer]:
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():
reg = self.request.user.registration
if reg in self.object.pool.juries.all():
context["my_note"] = Note.objects.get_or_create(passage=self.object, jury=self.request.user.registration)[0]
context["notes"] = NoteTable(self.object.notes.all())
elif self.request.user.registration.is_admin:
context["notes"] = NoteTable(self.object.notes.all())
if 'notes' in context and not self.object.observer:
if reg.is_volunteer:
notes = self.object.notes.all()
if not reg.is_admin \
or (reg != self.object.pool.jury_president
and reg not in self.object.pool.tournament.organizers.all()):
notes = [note for note in notes if note.has_any_note()]
context["notes"] = NoteTable(notes)
# Only display the observer column for 4-teams pools
context['notes']._sequence.pop()
context['notes']._sequence.remove('observer_oral')
if 'notes' in context and not self.request.user.registration.is_admin:
context['notes']._sequence.remove('update')
return context
@ -1634,8 +1664,9 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
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:
reg = request.user.registration
note = self.get_object()
if reg.is_admin or reg.is_volunteer and (note.jury == reg or note.passage.pool.jury_president == reg):
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()

View File

@ -797,9 +797,10 @@ class SolutionView(LoginRequiredMixin, View):
else:
passage_participant_qs = Passage.objects.none()
if not (user.registration.is_admin
or user.registration.is_volunteer and user.registration
in (solution.participation.tournament
if not solution.final_solution else Tournament.final_tournament()).organizers.all()
or (user.registration.is_volunteer
and user.registration in solution.tournament.organizers.all())
or (user.registration.is_volunteer
and user.registration.presided_pools.filter(tournament=solution.tournament).exists())
or user.registration.is_volunteer
and Passage.objects.filter(Q(pool__juries=user.registration)
| Q(pool__tournament__in=user.registration.organized_tournaments.all()),
@ -834,7 +835,8 @@ class SynthesisView(LoginRequiredMixin, View):
user = request.user
if not (user.registration.is_admin or user.registration.is_volunteer
and (user.registration in synthesis.passage.pool.juries.all()
or user.registration in synthesis.passage.pool.tournament.organizers.all())
or user.registration in synthesis.passage.pool.tournament.organizers.all()
or user.registration.presided_pools.filter(tournament=synthesis.passage.pool.tournament).exists())
or user.registration.participates and user.registration.team == synthesis.participation.team):
raise PermissionDenied
# Guess mime type of the file