Add extra access to juries

This commit is contained in:
Yohann D'ANELLO 2020-05-25 18:27:07 +02:00
parent 522ed088ef
commit 3d9e7136ac
8 changed files with 264 additions and 155 deletions

View File

@ -1,6 +1,6 @@
import random import random
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin, AccessMixin
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Q from django.db.models import Q
@ -13,7 +13,7 @@ from django.views import View
from django.views.generic import CreateView, UpdateView, DetailView, FormView from django.views.generic import CreateView, UpdateView, DetailView, FormView
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from tournament.forms import TeamForm, JoinTeam from tournament.forms import TeamForm, JoinTeam
from tournament.models import Team, Tournament from tournament.models import Team, Tournament, Pool
from tournament.views import AdminMixin, TeamMixin, OrgaMixin from tournament.views import AdminMixin, TeamMixin, OrgaMixin
from .forms import SignUpForm, TFJMUserForm, AdminUserForm, CoachUserForm from .forms import SignUpForm, TFJMUserForm, AdminUserForm, CoachUserForm
@ -177,7 +177,7 @@ class MyTeamView(TeamMixin, View):
return redirect("tournament:team_detail", pk=request.user.team.pk) return redirect("tournament:team_detail", pk=request.user.team.pk)
class DocumentView(LoginRequiredMixin, View): class DocumentView(AccessMixin, View):
""" """
View a PDF document, if we have the right. View a PDF document, if we have the right.
@ -194,14 +194,11 @@ class DocumentView(LoginRequiredMixin, View):
raise Http404(_("No %(verbose_name)s found matching the query") % raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': Document._meta.verbose_name}) {'verbose_name': Document._meta.verbose_name})
if request.user.is_authenticated:
grant = request.user.admin grant = request.user.admin
if isinstance(doc, Solution) or isinstance(doc, Synthesis) or isinstance(doc, MotivationLetter): if isinstance(doc, Solution) or isinstance(doc, Synthesis) or isinstance(doc, MotivationLetter):
grant = grant or doc.team == request.user.team or request.user in doc.team.tournament.organizers.all() grant = grant or doc.team == request.user.team or request.user in doc.tournament.organizers.all()
grant = grant or (doc.team.selected_for_final and request.user in Tournament.get_final().organizers.all())
if isinstance(doc, Synthesis) and request.user.organizes:
grant = True
if isinstance(doc, Solution): if isinstance(doc, Solution):
for pool in doc.pools.all(): for pool in doc.pools.all():
@ -212,6 +209,23 @@ class DocumentView(LoginRequiredMixin, View):
continue continue
if self.request.user.team in pool.teams.all(): if self.request.user.team in pool.teams.all():
grant = True grant = True
elif isinstance(doc, Synthesis):
for pool in request.user.pools.all(): # If the user is a jury in the pool
if doc.team in pool.teams.all() and doc.final == pool.tournament.final:
grant = True
break
else:
pool = Pool.objects.filter(extra_access_token=self.request.session["extra_access_token"])
if pool.exists():
pool = pool.get()
if isinstance(doc, Solution):
grant = doc in pool.solutions.all()
elif isinstance(doc, Synthesis):
grant = doc.team in pool.teams.all() and doc.final == pool.tournament.final
else:
grant = False
else:
grant = False
if not grant: if not grant:
raise PermissionDenied raise PermissionDenied

View File

@ -1,4 +1,5 @@
import os import os
import random
from django.core.mail import send_mail from django.core.mail import send_mail
from django.db import models from django.db import models
@ -338,6 +339,13 @@ class Pool(models.Model):
verbose_name=_("juries"), verbose_name=_("juries"),
) )
extra_access_token = models.CharField(
max_length=64,
default="",
verbose_name=_("extra access token"),
help_text=_("Let other users access to the pool data without logging in."),
)
@property @property
def problems(self): def problems(self):
""" """
@ -361,6 +369,13 @@ class Pool(models.Model):
from member.models import Synthesis from member.models import Synthesis
return Synthesis.objects.filter(team__in=self.teams.all(), round=self.round, final=self.tournament.final) return Synthesis.objects.filter(team__in=self.teams.all(), round=self.round, final=self.tournament.final)
def save(self, **kwargs):
if not self.extra_access_token:
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
code = "".join(random.choice(alphabet) for _ in range(64))
self.extra_access_token = code
super().save(**kwargs)
class Meta: class Meta:
verbose_name = _("pool") verbose_name = _("pool")
verbose_name_plural = _("pools") verbose_name_plural = _("pools")

View File

@ -3,7 +3,7 @@ import zipfile
from datetime import timedelta from datetime import timedelta
from io import BytesIO from io import BytesIO
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin, AccessMixin
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail from django.core.mail import send_mail
from django.db.models import Q from django.db.models import Q
@ -34,13 +34,15 @@ class AdminMixin(LoginRequiredMixin):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class OrgaMixin(LoginRequiredMixin): class OrgaMixin(AccessMixin):
""" """
If a view extends this mixin, then the view will be only accessible to administrators or organizers. If a view extends this mixin, then the view will be only accessible to administrators or organizers.
""" """
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.organizes: if not request.user.is_authenticated and not request.session["extra_access_token"]:
return self.handle_no_permission()
elif request.user.is_authenticated and not request.user.organizes:
raise PermissionDenied raise PermissionDenied
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
@ -247,7 +249,7 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["title"] = _("Information about team") context["title"] = _("Information about team")
context["ordered_solutions"] = self.object.solutions.order_by('problem').all() context["ordered_solutions"] = self.object.solutions.order_by('final', 'problem',).all()
context["team_users_emails"] = [user.email for user in self.object.users.all()] context["team_users_emails"] = [user.email for user in self.object.users.all()]
return context return context
@ -399,6 +401,7 @@ class SolutionsOrgaListView(OrgaMixin, SingleTableView):
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.is_authenticated:
context["tournaments"] = \ context["tournaments"] = \
Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments
@ -406,12 +409,14 @@ class SolutionsOrgaListView(OrgaMixin, SingleTableView):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
if not self.request.user.admin: if self.request.user.is_authenticated and not self.request.user.admin:
if self.request.user in Tournament.get_final().organizers.all(): if self.request.user in Tournament.get_final().organizers.all():
qs = qs.filter(Q(team__tournament__organizers=self.request.user) | Q(pools__juries=self.request.user) qs = qs.filter(Q(team__tournament__organizers=self.request.user) | Q(pools__juries=self.request.user)
| Q(final=True)) | Q(final=True))
else: else:
qs = qs.filter(Q(team__tournament__organizers=self.request.user) | Q(pools__juries=self.request.user)) qs = qs.filter(Q(team__tournament__organizers=self.request.user) | Q(pools__juries=self.request.user))
elif not self.request.user.is_authenticated:
qs = qs.filter(pools__extra_access_token=self.request.session["extra_access_token"])
return qs.order_by('final', 'team__tournament__date_start', 'team__tournament__name', 'team__trigram', return qs.order_by('final', 'team__tournament__date_start', 'team__tournament__name', 'team__trigram',
'problem',).distinct() 'problem',).distinct()
@ -529,6 +534,7 @@ class SynthesesOrgaListView(OrgaMixin, SingleTableView):
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.is_authenticated:
context["tournaments"] = \ context["tournaments"] = \
Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments Tournament.objects if self.request.user.admin else self.request.user.organized_tournaments
@ -536,7 +542,7 @@ class SynthesesOrgaListView(OrgaMixin, SingleTableView):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
if not self.request.user.admin: if self.request.user.is_authenticated and not self.request.user.admin:
if self.request.user in Tournament.get_final().organizers.all(): if self.request.user in Tournament.get_final().organizers.all():
qs = qs.filter(Q(team__tournament__organizers=self.request.user) qs = qs.filter(Q(team__tournament__organizers=self.request.user)
| Q(team__pools__juries=self.request.user) | Q(team__pools__juries=self.request.user)
@ -544,11 +550,18 @@ class SynthesesOrgaListView(OrgaMixin, SingleTableView):
else: else:
qs = qs.filter(Q(team__tournament__organizers=self.request.user) qs = qs.filter(Q(team__tournament__organizers=self.request.user)
| Q(team__pools__juries=self.request.user)) | Q(team__pools__juries=self.request.user))
elif not self.request.user.is_authenticated:
pool = Pool.objects.filter(extra_access_token=self.request.session["extra_access_token"])
if pool.exists():
pool = pool.get()
qs = qs.filter(team__pools=pool, final=pool.tournament.final)
else:
qs = qs.none()
return qs.order_by('final', 'team__tournament__date_start', 'team__tournament__name', 'team__trigram', return qs.order_by('final', 'team__tournament__date_start', 'team__tournament__name', 'team__trigram',
'round', 'source',).distinct() 'round', 'source',).distinct()
class PoolListView(LoginRequiredMixin, SingleTableView): class PoolListView(SingleTableView):
""" """
View the list of visible pools. View the list of visible pools.
Admins see all, juries see their own pools, organizers see the pools of their tournaments. Admins see all, juries see their own pools, organizers see the pools of their tournaments.
@ -560,10 +573,13 @@ class PoolListView(LoginRequiredMixin, SingleTableView):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
user = self.request.user user = self.request.user
if user.is_authenticated:
if not user.admin and user.organizes: if not user.admin and user.organizes:
qs = qs.filter(Q(juries=user) | Q(teams__tournament__organizers=user)) qs = qs.filter(Q(juries=user) | Q(teams__tournament__organizers=user))
elif user.participates: elif user.participates:
qs = qs.filter(teams=user.team) qs = qs.filter(teams=user.team)
else:
qs = qs.filter(extra_access_token=self.request.session["extra_access_token"])
qs = qs.distinct().order_by('id') qs = qs.distinct().order_by('id')
return qs return qs
@ -581,7 +597,7 @@ class PoolCreateView(AdminMixin, CreateView):
return reverse_lazy("tournament:pools") return reverse_lazy("tournament:pools")
class PoolDetailView(LoginRequiredMixin, DetailView): class PoolDetailView(DetailView):
""" """
See the detail of a pool. See the detail of a pool.
Teams and juries can download here defended solutions of the pool. Teams and juries can download here defended solutions of the pool.
@ -597,10 +613,13 @@ class PoolDetailView(LoginRequiredMixin, DetailView):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
user = self.request.user user = self.request.user
if user.is_authenticated:
if not user.admin and user.organizes: if not user.admin and user.organizes:
qs = qs.filter(Q(juries=user) | Q(teams__tournament__organizers=user)) qs = qs.filter(Q(juries=user) | Q(teams__tournament__organizers=user))
elif user.participates: elif user.participates:
qs = qs.filter(teams=user.team) qs = qs.filter(teams=user.team)
else:
qs = qs.filter(extra_access_token=self.request.session["extra_access_token"])
return qs.distinct() return qs.distinct()
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -608,7 +627,8 @@ class PoolDetailView(LoginRequiredMixin, DetailView):
pool = self.get_object() pool = self.get_object()
if "solutions_zip" in request.POST: if "solutions_zip" in request.POST:
if user.participates and pool.round == 2 and pool.tournament.date_solutions_2 > timezone.now(): if user.is_authenticated and user.participates and pool.round == 2\
and pool.tournament.date_solutions_2 > timezone.now():
raise PermissionDenied raise PermissionDenied
out = BytesIO() out = BytesIO()
@ -624,10 +644,7 @@ class PoolDetailView(LoginRequiredMixin, DetailView):
.format(_("Solutions of a pool for the round {round} of the tournament {tournament}.zip") .format(_("Solutions of a pool for the round {round} of the tournament {tournament}.zip")
.format(round=pool.round, tournament=str(pool.tournament)).replace(" ", "%20")) .format(round=pool.round, tournament=str(pool.tournament)).replace(" ", "%20"))
return resp return resp
elif "syntheses_zip" in request.POST and user.organizes: elif "syntheses_zip" in request.POST and (not user.is_authenticated or user.organizes):
if user.participates and pool.round == 2 and pool.tournament.date_solutions_2 > timezone.now():
raise PermissionDenied
out = BytesIO() out = BytesIO()
zf = zipfile.ZipFile(out, "w") zf = zipfile.ZipFile(out, "w")

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM2\n" "Project-Id-Version: TFJM2\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-12 18:25+0200\n" "POT-Creation-Date: 2020-05-25 18:23+0200\n"
"PO-Revision-Date: 2020-04-29 02:30+0000\n" "PO-Revision-Date: 2020-04-29 02:30+0000\n"
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n" "Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
"Language-Team: fr <LL@li.org>\n" "Language-Team: fr <LL@li.org>\n"
@ -44,11 +44,11 @@ msgstr "Adresse électronique"
#: apps/member/models.py:22 #: apps/member/models.py:22
msgid "This should be valid and will be controlled." msgid "This should be valid and will be controlled."
msgstr "" msgstr "Elle doit être valide et sera contrôlée."
#: apps/member/models.py:30 apps/member/models.py:244 apps/member/models.py:263 #: apps/member/models.py:30 apps/member/models.py:244 apps/member/models.py:263
#: apps/member/models.py:306 apps/tournament/models.py:285 #: apps/member/models.py:306 apps/tournament/models.py:286
#: apps/tournament/models.py:385 templates/member/tfjmuser_detail.html:16 #: apps/tournament/models.py:400 templates/member/tfjmuser_detail.html:16
msgid "team" msgid "team"
msgstr "équipe" msgstr "équipe"
@ -124,7 +124,7 @@ msgstr "téléphone du responsable"
msgid "responsible email" msgid "responsible email"
msgstr "email du responsable" msgstr "email du responsable"
#: apps/member/models.py:129 apps/tournament/models.py:44 #: apps/member/models.py:129 apps/tournament/models.py:45
#: templates/member/tfjmuser_detail.html:67 #: templates/member/tfjmuser_detail.html:67
#: templates/tournament/tournament_detail.html:42 #: templates/tournament/tournament_detail.html:42
msgid "description" msgid "description"
@ -138,13 +138,13 @@ msgstr "Administrateur"
msgid "Organizer" msgid "Organizer"
msgstr "Organisateur" msgstr "Organisateur"
#: apps/member/models.py:144 apps/tournament/models.py:89 #: apps/member/models.py:144 apps/tournament/models.py:90
#: apps/tournament/models.py:214 #: apps/tournament/models.py:215
msgid "year" msgid "year"
msgstr "année" msgstr "année"
#: apps/member/models.py:171 apps/member/models.py:214 #: apps/member/models.py:171 apps/member/models.py:214
#: apps/tournament/models.py:378 #: apps/tournament/models.py:393
msgid "user" msgid "user"
msgstr "utilisateur" msgstr "utilisateur"
@ -180,7 +180,7 @@ msgstr "Autorisation de droit à l'image"
msgid "Sanitary plug" msgid "Sanitary plug"
msgstr "Fiche sanitaire" msgstr "Fiche sanitaire"
#: apps/member/models.py:223 apps/tournament/models.py:396 #: apps/member/models.py:223 apps/tournament/models.py:411
msgid "Scholarship" msgid "Scholarship"
msgstr "Bourse" msgstr "Bourse"
@ -226,7 +226,7 @@ msgstr "solution pour la finale"
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: apps/member/models.py:286 apps/tournament/models.py:324 #: apps/member/models.py:286 apps/tournament/models.py:325
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
@ -253,15 +253,15 @@ msgstr "Rapporteur"
msgid "source" msgid "source"
msgstr "source" msgstr "source"
#: apps/member/models.py:320 apps/tournament/models.py:329 #: apps/member/models.py:320 apps/tournament/models.py:330
msgid "Round 1" msgid "Round 1"
msgstr "Tour 1" msgstr "Tour 1"
#: apps/member/models.py:321 apps/tournament/models.py:330 #: apps/member/models.py:321 apps/tournament/models.py:331
msgid "Round 2" msgid "Round 2"
msgstr "Tour 2" msgstr "Tour 2"
#: apps/member/models.py:323 apps/tournament/models.py:332 #: apps/member/models.py:323 apps/tournament/models.py:333
#: templates/tournament/pool_detail.html:18 #: templates/tournament/pool_detail.html:18
msgid "round" msgid "round"
msgstr "tour" msgstr "tour"
@ -303,40 +303,45 @@ msgstr "configuration"
msgid "configurations" msgid "configurations"
msgstr "configurations" msgstr "configurations"
#: apps/member/views.py:100 apps/member/views.py:140 #: apps/member/views.py:105 apps/member/views.py:145
msgid "You can't organize and participate at the same time." msgid "You can't organize and participate at the same time."
msgstr "Vous ne pouvez pas organiser et participer en même temps." msgstr "Vous ne pouvez pas organiser et participer en même temps."
#: apps/member/views.py:104 apps/member/views.py:144 #: apps/member/views.py:109 apps/member/views.py:149
msgid "You are already in a team." msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe." msgstr "Vous êtes déjà dans une équipe."
#: apps/member/views.py:148 #: apps/member/views.py:153
msgid "This team is full of coachs." msgid "This team is full of coachs."
msgstr "Cette équipe est pleine en encadrants." msgstr "Cette équipe est pleine en encadrants."
#: apps/member/views.py:152 #: apps/member/views.py:157
msgid "This team is full of participants." msgid "This team is full of participants."
msgstr "Cette équipe est pleine en participants." msgstr "Cette équipe est pleine en participants."
#: apps/member/views.py:156 #: apps/member/views.py:161
msgid "This team is already validated or waiting for validation." msgid "This team is already validated or waiting for validation."
msgstr "L'équipe est déjà en attente de validation." msgstr "L'équipe est déjà en attente de validation."
#: apps/member/views.py:220 templates/base.html:81 #: apps/member/views.py:194
#, python-format
msgid "No %(verbose_name)s found matching the query"
msgstr ""
#: apps/member/views.py:244 templates/base.html:81
msgid "All profiles" msgid "All profiles"
msgstr "Tous les profils" msgstr "Tous les profils"
#: apps/member/views.py:232 templates/base.html:80 #: apps/member/views.py:256 templates/base.html:80
msgid "Orphaned profiles" msgid "Orphaned profiles"
msgstr "Profils orphelins" msgstr "Profils orphelins"
#: apps/member/views.py:244 apps/tournament/forms.py:23 templates/base.html:83 #: apps/member/views.py:268 apps/tournament/forms.py:23 templates/base.html:83
msgid "Organizers" msgid "Organizers"
msgstr "Organisateurs" msgstr "Organisateurs"
#: apps/tournament/apps.py:10 apps/tournament/models.py:134 #: apps/tournament/apps.py:10 apps/tournament/models.py:135
#: apps/tournament/models.py:182 apps/tournament/tables.py:110 #: apps/tournament/models.py:183 apps/tournament/tables.py:110
#: templates/tournament/pool_detail.html:21 #: templates/tournament/pool_detail.html:21
#: templates/tournament/team_detail.html:21 #: templates/tournament/team_detail.html:21
msgid "tournament" msgid "tournament"
@ -400,7 +405,8 @@ msgstr "Problème n°%(problem)d"
msgid "" msgid ""
"Please keep filesize under %(max_size)s. Current filesize %(current_size)s" "Please keep filesize under %(max_size)s. Current filesize %(current_size)s"
msgstr "" msgstr ""
"Merci de ne pas dépasser les %(max_size)s. Le fichier envoyé pèse %(current_size)s." "Merci de ne pas dépasser les %(max_size)s. Le fichier envoyé pèse "
"%(current_size)s."
#: apps/tournament/forms.py:157 apps/tournament/forms.py:181 #: apps/tournament/forms.py:157 apps/tournament/forms.py:181
msgid "The file should be a PDF file." msgid "The file should be a PDF file."
@ -435,16 +441,16 @@ msgstr "Équipe 3"
msgid "Problem defended by team 3" msgid "Problem defended by team 3"
msgstr "Problème défendu par l'équipe 3" msgstr "Problème défendu par l'équipe 3"
#: apps/tournament/models.py:18 apps/tournament/models.py:169 #: apps/tournament/models.py:19 apps/tournament/models.py:170
#: templates/tournament/team_detail.html:12 #: templates/tournament/team_detail.html:12
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
#: apps/tournament/models.py:24 templates/tournament/tournament_detail.html:12 #: apps/tournament/models.py:25 templates/tournament/tournament_detail.html:12
msgid "organizers" msgid "organizers"
msgstr "organisateurs" msgstr "organisateurs"
#: apps/tournament/models.py:25 #: apps/tournament/models.py:26
msgid "" msgid ""
"List of all organizers that can see and manipulate data of the tournament " "List of all organizers that can see and manipulate data of the tournament "
"and the teams." "and the teams."
@ -452,71 +458,71 @@ msgstr ""
"Liste des organisateurs qui peuvent manipuler les données du tournoi et des " "Liste des organisateurs qui peuvent manipuler les données du tournoi et des "
"équipes." "équipes."
#: apps/tournament/models.py:29 templates/tournament/tournament_detail.html:15 #: apps/tournament/models.py:30 templates/tournament/tournament_detail.html:15
msgid "size" msgid "size"
msgstr "taille" msgstr "taille"
#: apps/tournament/models.py:30 #: apps/tournament/models.py:31
msgid "Number of teams that are allowed to join the tournament." msgid "Number of teams that are allowed to join the tournament."
msgstr "Nombre d'équipes qui sont autorisées à rejoindre le tournoi." msgstr "Nombre d'équipes qui sont autorisées à rejoindre le tournoi."
#: apps/tournament/models.py:35 templates/tournament/tournament_detail.html:18 #: apps/tournament/models.py:36 templates/tournament/tournament_detail.html:18
msgid "place" msgid "place"
msgstr "lieu" msgstr "lieu"
#: apps/tournament/models.py:39 templates/tournament/tournament_detail.html:21 #: apps/tournament/models.py:40 templates/tournament/tournament_detail.html:21
msgid "price" msgid "price"
msgstr "prix" msgstr "prix"
#: apps/tournament/models.py:40 #: apps/tournament/models.py:41
msgid "Price asked to participants. Free with a scholarship." msgid "Price asked to participants. Free with a scholarship."
msgstr "Prix demandé par participant. Gratuit pour les boursiers." msgstr "Prix demandé par participant. Gratuit pour les boursiers."
#: apps/tournament/models.py:49 #: apps/tournament/models.py:50
msgid "date start" msgid "date start"
msgstr "date de début" msgstr "date de début"
#: apps/tournament/models.py:54 #: apps/tournament/models.py:55
msgid "date end" msgid "date end"
msgstr "date de fin" msgstr "date de fin"
#: apps/tournament/models.py:59 templates/tournament/tournament_detail.html:27 #: apps/tournament/models.py:60 templates/tournament/tournament_detail.html:27
msgid "date of registration closing" msgid "date of registration closing"
msgstr "date de clôture des inscriptions" msgstr "date de clôture des inscriptions"
#: apps/tournament/models.py:64 templates/tournament/tournament_detail.html:30 #: apps/tournament/models.py:65 templates/tournament/tournament_detail.html:30
msgid "date of maximal solution submission" msgid "date of maximal solution submission"
msgstr "date d'envoi maximal des solutions" msgstr "date d'envoi maximal des solutions"
#: apps/tournament/models.py:69 templates/tournament/tournament_detail.html:33 #: apps/tournament/models.py:70 templates/tournament/tournament_detail.html:33
msgid "date of maximal syntheses submission for the first round" msgid "date of maximal syntheses submission for the first round"
msgstr "date d'envoi maximal des notes de synthèses du premier tour" msgstr "date d'envoi maximal des notes de synthèses du premier tour"
#: apps/tournament/models.py:74 templates/tournament/tournament_detail.html:36 #: apps/tournament/models.py:75 templates/tournament/tournament_detail.html:36
msgid "date when solutions of round 2 are available" msgid "date when solutions of round 2 are available"
msgstr "date à partir de laquelle les solutions du tour 2 sont disponibles" msgstr "date à partir de laquelle les solutions du tour 2 sont disponibles"
#: apps/tournament/models.py:79 templates/tournament/tournament_detail.html:39 #: apps/tournament/models.py:80 templates/tournament/tournament_detail.html:39
msgid "date of maximal syntheses submission for the second round" msgid "date of maximal syntheses submission for the second round"
msgstr "date d'envoi maximal des notes de synthèses pour le second tour" msgstr "date d'envoi maximal des notes de synthèses pour le second tour"
#: apps/tournament/models.py:83 #: apps/tournament/models.py:84
msgid "final tournament" msgid "final tournament"
msgstr "finale" msgstr "finale"
#: apps/tournament/models.py:84 #: apps/tournament/models.py:85
msgid "It should be only one final tournament." msgid "It should be only one final tournament."
msgstr "Il ne doit y avoir qu'une seule finale." msgstr "Il ne doit y avoir qu'une seule finale."
#: apps/tournament/models.py:135 #: apps/tournament/models.py:136
msgid "tournaments" msgid "tournaments"
msgstr "tournois" msgstr "tournois"
#: apps/tournament/models.py:174 templates/tournament/team_detail.html:15 #: apps/tournament/models.py:175 templates/tournament/team_detail.html:15
msgid "trigram" msgid "trigram"
msgstr "trigramme" msgstr "trigramme"
#: apps/tournament/models.py:175 #: apps/tournament/models.py:176
msgid "" msgid ""
"The trigram should be composed of 3 capitalize letters, that is a funny " "The trigram should be composed of 3 capitalize letters, that is a funny "
"acronym for the team." "acronym for the team."
@ -524,89 +530,97 @@ msgstr ""
"Le trigramme doit être composé de trois lettres en majuscule, qui doit être " "Le trigramme doit être composé de trois lettres en majuscule, qui doit être "
"un acronyme amusant représentant l'équipe." "un acronyme amusant représentant l'équipe."
#: apps/tournament/models.py:183 #: apps/tournament/models.py:184
msgid "The tournament where the team is registered." msgid "The tournament where the team is registered."
msgstr "Le tournoi où l'équipe est inscrite." msgstr "Le tournoi où l'équipe est inscrite."
#: apps/tournament/models.py:188 #: apps/tournament/models.py:189
msgid "inscription date" msgid "inscription date"
msgstr "date d'inscription" msgstr "date d'inscription"
#: apps/tournament/models.py:194 apps/tournament/models.py:405 #: apps/tournament/models.py:195 apps/tournament/models.py:420
msgid "Registration not validated" msgid "Registration not validated"
msgstr "Inscription non validée" msgstr "Inscription non validée"
#: apps/tournament/models.py:195 apps/tournament/models.py:406 #: apps/tournament/models.py:196 apps/tournament/models.py:421
msgid "Waiting for validation" msgid "Waiting for validation"
msgstr "En attente de validation" msgstr "En attente de validation"
#: apps/tournament/models.py:196 apps/tournament/models.py:407 #: apps/tournament/models.py:197 apps/tournament/models.py:422
msgid "Registration validated" msgid "Registration validated"
msgstr "Inscription validée" msgstr "Inscription validée"
#: apps/tournament/models.py:198 apps/tournament/models.py:409 #: apps/tournament/models.py:199 apps/tournament/models.py:424
#: templates/tournament/team_detail.html:32 #: templates/tournament/team_detail.html:32
msgid "validation status" msgid "validation status"
msgstr "statut de validation" msgstr "statut de validation"
#: apps/tournament/models.py:203 #: apps/tournament/models.py:204
msgid "selected for final" msgid "selected for final"
msgstr "sélectionnée pour la finale" msgstr "sélectionnée pour la finale"
#: apps/tournament/models.py:209 templates/tournament/team_detail.html:18 #: apps/tournament/models.py:210 templates/tournament/team_detail.html:18
msgid "access code" msgid "access code"
msgstr "code d'accès" msgstr "code d'accès"
#: apps/tournament/models.py:286 apps/tournament/models.py:318 #: apps/tournament/models.py:287 apps/tournament/models.py:319
#: templates/tournament/pool_detail.html:15 #: templates/tournament/pool_detail.html:15
msgid "teams" msgid "teams"
msgstr "équipes" msgstr "équipes"
#: apps/tournament/models.py:338 templates/tournament/pool_detail.html:12 #: apps/tournament/models.py:339 templates/tournament/pool_detail.html:12
msgid "juries" msgid "juries"
msgstr "jurys" msgstr "jurys"
#: apps/tournament/models.py:365 #: apps/tournament/models.py:345
msgid "extra access token"
msgstr "code d'accès spécial"
#: apps/tournament/models.py:346
msgid "Let other users access to the pool data without logging in."
msgstr "Permet à d'autres utilisateurs d'accéder au contenu de la poule sans connexion."
#: apps/tournament/models.py:380
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
#: apps/tournament/models.py:366 #: apps/tournament/models.py:381
msgid "pools" msgid "pools"
msgstr "poules" msgstr "poules"
#: apps/tournament/models.py:391 #: apps/tournament/models.py:406
msgid "Not paid" msgid "Not paid"
msgstr "Non payé" msgstr "Non payé"
#: apps/tournament/models.py:392 #: apps/tournament/models.py:407
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
#: apps/tournament/models.py:393 #: apps/tournament/models.py:408
msgid "Bank check" msgid "Bank check"
msgstr "Chèque bancaire" msgstr "Chèque bancaire"
#: apps/tournament/models.py:394 #: apps/tournament/models.py:409
msgid "Bank transfer" msgid "Bank transfer"
msgstr "Virement bancaire" msgstr "Virement bancaire"
#: apps/tournament/models.py:395 #: apps/tournament/models.py:410
msgid "Cash" msgid "Cash"
msgstr "Espèces" msgstr "Espèces"
#: apps/tournament/models.py:399 #: apps/tournament/models.py:414
msgid "payment method" msgid "payment method"
msgstr "moyen de paiement" msgstr "moyen de paiement"
#: apps/tournament/models.py:413 #: apps/tournament/models.py:428
msgid "payment" msgid "payment"
msgstr "paiement" msgstr "paiement"
#: apps/tournament/models.py:414 #: apps/tournament/models.py:429
msgid "payments" msgid "payments"
msgstr "paiements" msgstr "paiements"
#: apps/tournament/models.py:417 #: apps/tournament/models.py:432
#, python-brace-format #, python-brace-format
msgid "Payment of {user}" msgid "Payment of {user}"
msgstr "Paiement de {user}" msgstr "Paiement de {user}"
@ -633,71 +647,71 @@ msgstr "Télécharger"
msgid "Problems" msgid "Problems"
msgstr "Problèmes" msgstr "Problèmes"
#: apps/tournament/views.py:66 #: apps/tournament/views.py:68
msgid "Tournaments list" msgid "Tournaments list"
msgstr "Liste des tournois" msgstr "Liste des tournois"
#: apps/tournament/views.py:89 #: apps/tournament/views.py:91
msgid "Add tournament" msgid "Add tournament"
msgstr "Ajouter un tournoi" msgstr "Ajouter un tournoi"
#: apps/tournament/views.py:106 #: apps/tournament/views.py:108
#, python-brace-format #, python-brace-format
msgid "Tournament of {name}" msgid "Tournament of {name}"
msgstr "Tournoi de {name}" msgstr "Tournoi de {name}"
#: apps/tournament/views.py:140 #: apps/tournament/views.py:146
msgid "Update tournament" msgid "Update tournament"
msgstr "Modifier le tournoi" msgstr "Modifier le tournoi"
#: apps/tournament/views.py:187 apps/tournament/views.py:315 #: apps/tournament/views.py:195 apps/tournament/views.py:323
#, python-brace-format #, python-brace-format
msgid "Solutions for team {team}.zip" msgid "Solutions for team {team}.zip"
msgstr "Solutions pour l'équipe {team}.zip" msgstr "Solutions pour l'équipe {team}.zip"
#: apps/tournament/views.py:243 #: apps/tournament/views.py:251
msgid "Information about team" msgid "Information about team"
msgstr "Informations sur l'équipe" msgstr "Informations sur l'équipe"
#: apps/tournament/views.py:258 #: apps/tournament/views.py:266
msgid "Update team" msgid "Update team"
msgstr "Modifier l'équipe" msgstr "Modifier l'équipe"
#: apps/tournament/views.py:276 #: apps/tournament/views.py:284
msgid "Add organizer" msgid "Add organizer"
msgstr "Ajouter un organisateur" msgstr "Ajouter un organisateur"
#: apps/tournament/views.py:299 templates/base.html:108 templates/base.html:126 #: apps/tournament/views.py:307 templates/base.html:108 templates/base.html:118
#: templates/tournament/pool_detail.html:31 #: templates/base.html:132 templates/tournament/pool_detail.html:31
msgid "Solutions" msgid "Solutions"
msgstr "Solutions" msgstr "Solutions"
#: apps/tournament/views.py:339 #: apps/tournament/views.py:347
msgid "" msgid ""
"You can't publish your solution anymore. Deadline: {date:%m-%d-%Y %H:%M}." "You can't publish your solution anymore. Deadline: {date:%m-%d-%Y %H:%M}."
msgstr "" msgstr ""
"Vous ne pouvez plus publier vos solutions. Deadline : {date:%d/%m/%Y %H:%M}." "Vous ne pouvez plus publier vos solutions. Deadline : {date:%d/%m/%Y %H:%M}."
#: apps/tournament/views.py:368 #: apps/tournament/views.py:376
msgid "All solutions" msgid "All solutions"
msgstr "Toutes les solutions" msgstr "Toutes les solutions"
#: apps/tournament/views.py:387 #: apps/tournament/views.py:395
#, python-brace-format #, python-brace-format
msgid "Solutions for tournament {tournament}.zip" msgid "Solutions for tournament {tournament}.zip"
msgstr "Solutions pour le tournoi {tournament}.zip" msgstr "Solutions pour le tournoi {tournament}.zip"
#: apps/tournament/views.py:417 templates/base.html:111 templates/base.html:129 #: apps/tournament/views.py:432 templates/base.html:111 templates/base.html:121
#: templates/tournament/pool_detail.html:57 #: templates/base.html:135 templates/tournament/pool_detail.html:57
msgid "Syntheses" msgid "Syntheses"
msgstr "Synthèses" msgstr "Synthèses"
#: apps/tournament/views.py:433 #: apps/tournament/views.py:448
#, python-brace-format #, python-brace-format
msgid "Syntheses for team {team}.zip" msgid "Syntheses for team {team}.zip"
msgstr "Notes de synthèse de l'équipe {team}.zip" msgstr "Notes de synthèse de l'équipe {team}.zip"
#: apps/tournament/views.py:458 #: apps/tournament/views.py:473
msgid "" msgid ""
"You can't publish your synthesis anymore for the first round. Deadline: " "You can't publish your synthesis anymore for the first round. Deadline: "
"{date:%m-%d-%Y %H:%M}." "{date:%m-%d-%Y %H:%M}."
@ -705,7 +719,7 @@ msgstr ""
"Vous ne pouvez plus envoyer vos notes de synthèse pour le premier tour. " "Vous ne pouvez plus envoyer vos notes de synthèse pour le premier tour. "
"Deadline : {date:%d/%m/%Y %h:%M}." "Deadline : {date:%d/%m/%Y %h:%M}."
#: apps/tournament/views.py:464 #: apps/tournament/views.py:479
msgid "" msgid ""
"You can't publish your synthesis anymore for the second round. Deadline: " "You can't publish your synthesis anymore for the second round. Deadline: "
"{date:%m-%d-%Y %H:%M}." "{date:%m-%d-%Y %H:%M}."
@ -713,34 +727,34 @@ msgstr ""
"Vous ne pouvez plus envoyer vos notes de synthèse pour le second tour. " "Vous ne pouvez plus envoyer vos notes de synthèse pour le second tour. "
"Deadline : {date:%d/%m/%Y %h:%M}." "Deadline : {date:%d/%m/%Y %h:%M}."
#: apps/tournament/views.py:494 #: apps/tournament/views.py:509
msgid "All syntheses" msgid "All syntheses"
msgstr "Toutes les notes de synthèses" msgstr "Toutes les notes de synthèses"
#: apps/tournament/views.py:513 #: apps/tournament/views.py:528
#, python-brace-format #, python-brace-format
msgid "Syntheses for tournament {tournament}.zip" msgid "Syntheses for tournament {tournament}.zip"
msgstr "Notes de synthèse pour le tournoi {tournament}.zip" msgstr "Notes de synthèse pour le tournoi {tournament}.zip"
#: apps/tournament/views.py:542 templates/base.html:133 #: apps/tournament/views.py:571 templates/base.html:125 templates/base.html:138
msgid "Pools" msgid "Pools"
msgstr "Poules" msgstr "Poules"
#: apps/tournament/views.py:563 #: apps/tournament/views.py:594
msgid "Create pool" msgid "Create pool"
msgstr "Créer une poule" msgstr "Créer une poule"
#: apps/tournament/views.py:580 #: apps/tournament/views.py:611
msgid "Pool detail" msgid "Pool detail"
msgstr "Détails d'une poule" msgstr "Détails d'une poule"
#: apps/tournament/views.py:609 #: apps/tournament/views.py:644
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Solutions of a pool for the round {round} of the tournament {tournament}.zip" "Solutions of a pool for the round {round} of the tournament {tournament}.zip"
msgstr "Solutions d'une poule du tour {round} du tournoi {tournament}.zip" msgstr "Solutions d'une poule du tour {round} du tournoi {tournament}.zip"
#: apps/tournament/views.py:626 #: apps/tournament/views.py:658
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Syntheses of a pool for the round {round} of the tournament {tournament}.zip" "Syntheses of a pool for the round {round} of the tournament {tournament}.zip"
@ -826,38 +840,30 @@ msgstr "Rejoindre une équipe"
msgid "My team" msgid "My team"
msgstr "Mon équipe" msgstr "Mon équipe"
#: templates/base.html:118 #: templates/base.html:144
msgid "Add a tournament"
msgstr "Ajouter un tournoi"
#: templates/base.html:121
msgid "Add an organizer"
msgstr "Ajouter un organisateur"
#: templates/base.html:138
msgid "Make a gift" msgid "Make a gift"
msgstr "Faire un don" msgstr "Faire un don"
#: templates/base.html:142 #: templates/base.html:148
msgid "Administration" msgid "Administration"
msgstr "Administration" msgstr "Administration"
#: templates/base.html:149 #: templates/base.html:155
msgid "Return to admin view" msgid "Return to admin view"
msgstr "Retour à l'interface administrateur" msgstr "Retour à l'interface administrateur"
#: templates/base.html:154 templates/registration/login.html:7 #: templates/base.html:160 templates/registration/login.html:7
#: templates/registration/login.html:8 templates/registration/login.html:22 #: templates/registration/login.html:8 templates/registration/login.html:22
#: templates/registration/password_reset_complete.html:10 #: templates/registration/password_reset_complete.html:10
msgid "Log in" msgid "Log in"
msgstr "Connexion" msgstr "Connexion"
#: templates/base.html:157 templates/registration/signup.html:5 #: templates/base.html:163 templates/registration/signup.html:5
#: templates/registration/signup.html:8 templates/registration/signup.html:14 #: templates/registration/signup.html:8 templates/registration/signup.html:14
msgid "Sign up" msgid "Sign up"
msgstr "S'inscrire" msgstr "S'inscrire"
#: templates/base.html:161 #: templates/base.html:167
msgid "Log out" msgid "Log out"
msgstr "Déconnexion" msgstr "Déconnexion"
@ -867,7 +873,7 @@ msgid "Field filters"
msgstr "Filtres" msgstr "Filtres"
#: templates/django_filters/rest_framework/form.html:5 #: templates/django_filters/rest_framework/form.html:5
#: templates/member/my_account.html:8 templates/tournament/add_organizer.html:9 #: templates/member/my_account.html:9 templates/tournament/add_organizer.html:9
#: templates/tournament/pool_form.html:9 #: templates/tournament/pool_form.html:9
#: templates/tournament/solutions_list.html:24 #: templates/tournament/solutions_list.html:24
#: templates/tournament/syntheses_list.html:40 #: templates/tournament/syntheses_list.html:40
@ -876,10 +882,14 @@ msgstr "Filtres"
msgid "Submit" msgid "Submit"
msgstr "Envoyer" msgstr "Envoyer"
#: templates/member/my_account.html:13 #: templates/member/my_account.html:14
msgid "Update my password" msgid "Update my password"
msgstr "Changer mon mot de passe" msgstr "Changer mon mot de passe"
#: templates/member/profile_list.html:9
msgid "Add an organizer"
msgstr "Ajouter un organisateur"
#: templates/member/tfjmuser_detail.html:12 #: templates/member/tfjmuser_detail.html:12
msgid "role" msgid "role"
msgstr "rôle" msgstr "rôle"
@ -1045,7 +1055,7 @@ msgid "Solutions will be available here for teams from:"
msgstr "Les solutions seront disponibles ici pour les équipes à partir du :" msgstr "Les solutions seront disponibles ici pour les équipes à partir du :"
#: templates/tournament/pool_detail.html:49 #: templates/tournament/pool_detail.html:49
#: templates/tournament/pool_detail.html:74 #: templates/tournament/pool_detail.html:73
msgid "Download ZIP archive" msgid "Download ZIP archive"
msgstr "Télécharger l'archive ZIP" msgstr "Télécharger l'archive ZIP"
@ -1058,6 +1068,15 @@ msgstr "Le modèle de note de synthèse est disponible ici :"
msgid "Pool list" msgid "Pool list"
msgstr "Liste des poules" msgstr "Liste des poules"
#: templates/tournament/pool_detail.html:89
msgid ""
"Give this link to juries to access this page (warning: should stay "
"confidential and only given to juries of this pool):"
msgstr ""
"Donnez ce lien aux jurys pour leur permettre d'accéder à cette page "
"(attention : ce lien doit rester confidentiel et ne doit être donné "
"exclusivement qu'à des jurys) :"
#: templates/tournament/pool_list.html:10 #: templates/tournament/pool_list.html:10
msgid "Add pool" msgid "Add pool"
msgstr "Ajouter une poule" msgstr "Ajouter une poule"
@ -1210,10 +1229,14 @@ msgstr "Envoyer un mail à toutes les personnes dans une équipe"
msgid "Send a mail to all people that are in a valid team" msgid "Send a mail to all people that are in a valid team"
msgstr "Envoyer un mail à toutes les personnes dans une équipe validée" msgstr "Envoyer un mail à toutes les personnes dans une équipe validée"
#: tfjm/settings.py:146 #: templates/tournament/tournament_list.html:15
msgid "Add a tournament"
msgstr "Ajouter un tournoi"
#: tfjm/settings.py:147
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: tfjm/settings.py:147 #: tfjm/settings.py:148
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"

View File

@ -125,6 +125,20 @@
<a class="nav-link" href="{% url "tournament:pools" %}"><i class="fas fa-swimming-pool"></i> {% trans "Pools" %}</a> <a class="nav-link" href="{% url "tournament:pools" %}"><i class="fas fa-swimming-pool"></i> {% trans "Pools" %}</a>
</li> </li>
{% endif %} {% endif %}
{% if not user.is_authenticated and request.session.extra_access_token %}
{# Juries can access to pool data without logging in. #}
<li class="nav-item active">
<a class="nav-link" href="{% url "tournament:all_solutions" %}"><i class="fas fa-lightbulb"></i> {% trans "Solutions" %}</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="{% url "tournament:all_syntheses" %}"><i class="fas fa-feather"></i> {% trans "Syntheses" %}</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="{% url "tournament:pools" %}"><i class="fas fa-swimming-pool"></i> {% trans "Pools" %}</a>
</li>
{% endif %}
<li class="nav-item active"> <li class="nav-item active">
<a class="nav-link" href="https://www.helloasso.com/associations/animath/formulaires/5/widget"><i <a class="nav-link" href="https://www.helloasso.com/associations/animath/formulaires/5/widget"><i
class="fas fa-hand-holding-heart"></i> {% trans "Make a gift" %}</a> class="fas fa-hand-holding-heart"></i> {% trans "Make a gift" %}</a>

View File

@ -61,13 +61,12 @@
{% trans "Templates for syntheses are available here:" %} {% trans "Templates for syntheses are available here:" %}
<a data-turbolinks="false" href="{% static "Fiche synthèse.pdf" %}">PDF</a> -- <a data-turbolinks="false" href="{% static "Fiche synthèse.tex" %}">TEX</a> <a data-turbolinks="false" href="{% static "Fiche synthèse.pdf" %}">PDF</a> -- <a data-turbolinks="false" href="{% static "Fiche synthèse.tex" %}">TEX</a>
</div> </div>
{% if user.organizes %} {% if user.organizes or not user.is_authenticated %}
<ul> <ul>
{% for synthesis in pool.syntheses.all %} {% for synthesis in pool.syntheses.all %}
<li><a data-turbolinks="false" href="{{ synthesis.file.url }}">{{ synthesis }}</a></li> <li><a data-turbolinks="false" href="{{ synthesis.file.url }}">{{ synthesis }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div>
<div class="card-footer text-center"> <div class="card-footer text-center">
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
@ -76,10 +75,20 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div>
<hr> <hr>
<div class="text-center"> <div class="text-center">
<a class="btn btn-block btn-primary" href="{% url "tournament:pools" %}">{% trans "Pool list" %}</a> <a class="btn btn-block btn-primary" href="{% url "tournament:pools" %}">{% trans "Pool list" %}</a>
</div> </div>
{% if user.organizes or not user.is_authenticated %}
<hr>
<div class="alert alert-warning">
{% trans "Give this link to juries to access this page (warning: should stay confidential and only given to juries of this pool):" %}<br>
<a href="{% url "tournament:pool_detail" pk=pool.pk %}?extra_access_token={{ pool.extra_access_token }}">
https://{{ request.get_host }}{% url "tournament:pool_detail" pk=pool.pk %}?extra_access_token={{ pool.extra_access_token }}</a>
</div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -64,6 +64,22 @@ class SessionMiddleware(object):
return response return response
class ExtraAccessMiddleware(object):
"""
This middleware allows some non authenticated people to access to pool data.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if "extra_access_token" in request.GET:
request.session["extra_access_token"] = request.GET["extra_access_token"]
else:
request.session.setdefault("extra_access_token", "")
return self.get_response(request)
class TurbolinksMiddleware(object): class TurbolinksMiddleware(object):
""" """
Send the `Turbolinks-Location` header in response to a visit that was redirected, Send the `Turbolinks-Location` header in response to a visit that was redirected,

View File

@ -71,6 +71,7 @@ MIDDLEWARE = [
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware',
'tfjm.middlewares.SessionMiddleware', 'tfjm.middlewares.SessionMiddleware',
'tfjm.middlewares.ExtraAccessMiddleware',
'tfjm.middlewares.TurbolinksMiddleware', 'tfjm.middlewares.TurbolinksMiddleware',
] ]