import random from datetime import timezone from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied from django.db.models import Q from django.http import FileResponse from django.shortcuts import redirect from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from django.views import View from django.views.generic import CreateView, UpdateView, DetailView, FormView from django_tables2 import SingleTableView from tournament.forms import TeamForm, JoinTeam from tournament.models import Team from tournament.views import AdminMixin, TeamMixin from .forms import SignUpForm, TFJMUserForm, AdminUserForm, CoachUserForm from .models import TFJMUser, Document, Solution, MotivationLetter, Synthesis from .tables import UserTable class CreateUserView(CreateView): model = TFJMUser form_class = SignUpForm template_name = "registration/signup.html" class MyAccountView(LoginRequiredMixin, UpdateView): model = TFJMUser template_name = "member/my_account.html" def get_form_class(self): return AdminUserForm if self.request.user.organizes else TFJMUserForm \ if self.request.user.role == "3participant" else CoachUserForm def get_object(self, queryset=None): return self.request.user class UserDetailView(LoginRequiredMixin, DetailView): model = TFJMUser form_class = TFJMUserForm context_object_name = "tfjmuser" def dispatch(self, request, *args, **kwargs): if isinstance(request.user, AnonymousUser): raise PermissionDenied self.object = self.get_object() if not request.user.admin \ and (self.object.team is not None and request.user not in self.object.team.tournament.organizers.all())\ and self.request.user != self.object: raise PermissionDenied return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): if "view_as" in request.POST: session = request.session session["admin"] = request.user.pk obj = self.get_object() session["_fake_user_id"] = obj.pk return redirect(request.path) return self.get(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["title"] = str(self.object) return context class AddTeamView(LoginRequiredMixin, CreateView): model = Team form_class = TeamForm def form_valid(self, form): if self.request.user.organizes: form.add_error('name', _("You can't organize and participate at the same time.")) return self.form_invalid(form) if self.request.user.team: form.add_error('name', _("You are already in a team.")) return self.form_invalid(form) team = form.instance alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789" code = "" for i in range(6): code += random.choice(alphabet) team.access_code = code team.validation_status = "0invalid" team.save() team.refresh_from_db() self.request.user.team = team self.request.user.save() return super().form_valid(form) def get_success_url(self): return reverse_lazy("member:my_team") class JoinTeamView(LoginRequiredMixin, FormView): model = Team form_class = JoinTeam template_name = "tournament/team_form.html" def form_valid(self, form): team = form.cleaned_data["team"] if self.request.user.organizes: form.add_error('access_code', _("You can't organize and participate at the same time.")) return self.form_invalid(form) if self.request.user.team: form.add_error('access_code', _("You are already in a team.")) return self.form_invalid(form) if self.request.user.role == '2coach' and team.encadrants.size() == 3: form.add_error('access_code', _("This team is full of coachs.")) return self.form_invalid(form) if self.request.user.role == '3participant' and team.participants.size() == 5: form.add_error('access_code', _("This team is full of participants.")) return self.form_invalid(form) self.request.user.team = team self.request.user.save() return super().form_valid(form) def get_success_url(self): return reverse_lazy("member:my_team") class MyTeamView(TeamMixin, View): def get(self, request, *args, **kwargs): return redirect("tournament:team_detail", pk=request.user.team.pk) class DocumentView(LoginRequiredMixin, View): def get(self, request, *args, **kwargs): doc = Document.objects.get(file=self.kwargs["file"]) grant = request.user.admin 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() if isinstance(doc, Synthesis) and request.user.organizes: grant = True if isinstance(doc, Solution): for pool in doc.pools.all(): if pool.round == 2 and timezone.now() < doc.tournament.date_solutions_2: continue if self.request.user.team in pool.teams.all(): grant = True if not grant: raise PermissionDenied return FileResponse(doc.file, content_type="application/pdf") class ProfileListView(AdminMixin, SingleTableView): model = TFJMUser queryset = TFJMUser.objects.order_by("role", "last_name", "first_name") table_class = UserTable template_name = "member/profile_list.html" extra_context = dict(title=_("All profiles")) class OrphanedProfileListView(AdminMixin, SingleTableView): model = TFJMUser queryset = TFJMUser.objects.filter((Q(role="2coach") | Q(role="3participant")) & Q(team__isnull=True))\ .order_by("role", "last_name", "first_name") table_class = UserTable template_name = "member/profile_list.html" extra_context = dict(title=_("Orphaned profiles")) class OrganizersListView(AdminMixin, SingleTableView): model = TFJMUser queryset = TFJMUser.objects.filter(Q(role="0admin") | Q(role="1volunteer"))\ .order_by("role", "last_name", "first_name") table_class = UserTable template_name = "member/profile_list.html" extra_context = dict(title=_("Organizers")) class ResetAdminView(AdminMixin, View): def dispatch(self, request, *args, **kwargs): if "_fake_user_id" in request.session: del request.session["_fake_user_id"] return redirect(request.GET["path"])