from io import BytesIO from zipfile import ZipFile from corres2math.lists import get_sympa_client from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied from django.db import transaction from django.http import HttpResponse from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, FormView, RedirectView, UpdateView from django.shortcuts import redirect from magic import Magic from .forms import JoinTeamForm, ParticipationForm, TeamForm, UploadVideoForm from .models import Participation, Team, Video class CreateTeamView(LoginRequiredMixin, CreateView): model = Team form_class = TeamForm extra_context = dict(title=_("Create team")) template_name = "participation/create_team.html" def dispatch(self, request, *args, **kwargs): user = request.user registration = user.registration if not registration.participates: raise PermissionDenied(_("You don't participate, so you can't create a team.")) elif registration.team: raise PermissionDenied(_("You are already in a team.")) return super().dispatch(request, *args, **kwargs) @transaction.atomic def form_valid(self, form): ret = super().form_valid(form) user = self.request.user registration = user.registration registration.team = form.instance registration.save() get_sympa_client().subscribe(user.email, f"equipe-{form.instance.trigram.lower()}", False, f"{user.first_name} {user.last_name}") return ret def get_success_url(self): return reverse_lazy("participation:team_detail", args=(self.object.pk,)) class JoinTeamView(LoginRequiredMixin, FormView): model = Team form_class = JoinTeamForm extra_context = dict(title=_("Join team")) template_name = "participation/create_team.html" def dispatch(self, request, *args, **kwargs): user = request.user registration = user.registration if not registration.participates: raise PermissionDenied(_("You don't participate, so you can't create a team.")) elif registration.team: raise PermissionDenied(_("You are already in a team.")) return super().dispatch(request, *args, **kwargs) @transaction.atomic def form_valid(self, form): self.object = form.instance ret = super().form_valid(form) user = self.request.user registration = user.registration registration.team = form.instance registration.save() get_sympa_client().subscribe(user.email, f"equipe-{form.instance.trigram.lower()}", False, f"{user.first_name} {user.last_name}") return ret def get_success_url(self): return reverse_lazy("participation:team_detail", args=(self.object.pk,)) class MyTeamDetailView(LoginRequiredMixin, RedirectView): def get_redirect_url(self, *args, **kwargs): user = self.request.user registration = user.registration if registration.participates: if registration.team: return reverse_lazy("participation:team_detail", args=(registration.team_id,)) raise PermissionDenied(_("You are not in a team.")) raise PermissionDenied(_("You don't participate, so you don't have any team.")) class TeamDetailView(LoginRequiredMixin, DetailView): model = Team def get(self, request, *args, **kwargs): user = request.user if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: return super().get(request, *args, **kwargs) raise PermissionDenied def post(self, request, *args, **kwargs): if request.user.registration.participates: if "request-validation" in request.POST: request.user.registration.team.participation.valid = False # TODO Send mail to admins request.user.registration.team.participation.save() return redirect(request.path) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) team = self.object context["can_validate"] = team.students.count() >= 3 and \ all(r.email_confirmed for r in team.students.all()) and \ all(r.photo_authorization for r in team.students.all()) and \ team.participation.problem return context class TeamUpdateView(LoginRequiredMixin, UpdateView): model = Team form_class = TeamForm template_name = "participation/update_team.html" def dispatch(self, request, *args, **kwargs): user = request.user if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: return super().dispatch(request, *args, **kwargs) raise PermissionDenied def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["participation_form"] = ParticipationForm(data=self.request.POST or None, instance=self.object.participation) return context @transaction.atomic def form_valid(self, form): participation_form = ParticipationForm(data=self.request.POST or None, instance=self.object.participation) if not participation_form.is_valid(): return self.form_invalid(form) participation_form.save() return super().form_valid(form) def get_success_url(self): return reverse_lazy("participation:team_detail", args=(self.object.pk,)) class TeamAuthorizationsView(LoginRequiredMixin, DetailView): model = Team def dispatch(self, request, *args, **kwargs): user = request.user if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]: return super().dispatch(request, *args, **kwargs) raise PermissionDenied def get(self, request, *args, **kwargs): team = self.get_object() output = BytesIO() zf = ZipFile(output, "w") for student in team.students.all(): magic = Magic(mime=True) mime_type = magic.from_file("media/" + student.photo_authorization.name) ext = mime_type.split("/")[1].replace("jpeg", "jpg") zf.write("media/" + student.photo_authorization.name, _("Photo authorization of {student}.{ext}").format(student=str(student), ext=ext)) zf.close() response = HttpResponse(content_type="application/zip") response["Content-Disposition"] = "attachment; filename=\"{filename}\"" \ .format(filename=_("Photo authorizations of team {trigram}.zip").format(trigram=team.trigram)) response.write(output.getvalue()) return response class MyParticipationDetailView(LoginRequiredMixin, RedirectView): def get_redirect_url(self, *args, **kwargs): user = self.request.user registration = user.registration if registration.participates: if registration.team: return reverse_lazy("participation:participation_detail", args=(registration.team.participation.id,)) raise PermissionDenied(_("You are not in a team.")) raise PermissionDenied(_("You don't participate, so you don't have any team.")) class ParticipationDetailView(LoginRequiredMixin, DetailView): model = Participation def dispatch(self, request, *args, **kwargs): user = request.user if not self.get_object().valid: raise PermissionDenied(_("The team is not validated yet.")) if user.registration.is_admin or user.registration.participates \ and user.registration.team.participation.pk == kwargs["pk"]: return super().dispatch(request, *args, **kwargs) raise PermissionDenied class UploadVideoView(LoginRequiredMixin, UpdateView): model = Video form_class = UploadVideoForm template_name = "participation/upload_video.html" def dispatch(self, request, *args, **kwargs): user = request.user if user.registration.is_admin or user.registration.participates \ and user.registration.team.participation.pk == self.get_object().participation.pk: return super().dispatch(request, *args, **kwargs) raise PermissionDenied def get_success_url(self): return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,))