mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-07-04 03:32:10 +02:00
Clone Corres2math platform
This commit is contained in:
319
apps/registration/views.py
Normal file
319
apps/registration/views.py
Normal file
@ -0,0 +1,319 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from tfjm.tokens import email_validation_token
|
||||
from tfjm.views import AdminMixin
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied, ValidationError
|
||||
from django.db import transaction
|
||||
from django.http import FileResponse, Http404
|
||||
from django.shortcuts import redirect, resolve_url
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
|
||||
from django_tables2 import SingleTableView
|
||||
from magic import Magic
|
||||
from participation.models import Phase
|
||||
|
||||
from .forms import CoachRegistrationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm
|
||||
from .models import Registration, StudentRegistration
|
||||
from .tables import RegistrationTable
|
||||
|
||||
|
||||
class SignupView(CreateView):
|
||||
"""
|
||||
Signup, as a participant or a coach.
|
||||
"""
|
||||
model = User
|
||||
form_class = SignupForm
|
||||
template_name = "registration/signup.html"
|
||||
extra_context = dict(title=_("Sign up"))
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
"""
|
||||
The signup view is available only during the first phase.
|
||||
"""
|
||||
current_phase = Phase.current_phase()
|
||||
if not current_phase or current_phase.phase_number >= 2:
|
||||
raise PermissionDenied(_("You can't register now."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data()
|
||||
|
||||
context["student_registration_form"] = StudentRegistrationForm(self.request.POST or None)
|
||||
context["coach_registration_form"] = CoachRegistrationForm(self.request.POST or None)
|
||||
|
||||
del context["student_registration_form"].fields["team"]
|
||||
del context["student_registration_form"].fields["email_confirmed"]
|
||||
del context["coach_registration_form"].fields["team"]
|
||||
del context["coach_registration_form"].fields["email_confirmed"]
|
||||
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
role = form.cleaned_data["role"]
|
||||
if role == "participant":
|
||||
registration_form = StudentRegistrationForm(self.request.POST)
|
||||
else:
|
||||
registration_form = CoachRegistrationForm(self.request.POST)
|
||||
del registration_form.fields["team"]
|
||||
del registration_form.fields["email_confirmed"]
|
||||
|
||||
if not registration_form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
|
||||
ret = super().form_valid(form)
|
||||
registration = registration_form.instance
|
||||
registration.user = form.instance
|
||||
registration.save()
|
||||
|
||||
return ret
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("registration:email_validation_sent")
|
||||
|
||||
|
||||
class UserValidateView(TemplateView):
|
||||
"""
|
||||
A view to validate the email address.
|
||||
"""
|
||||
title = _("Email validation")
|
||||
template_name = 'registration/email_validation_complete.html'
|
||||
extra_context = dict(title=_("Validate email"))
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""
|
||||
With a given token and user id (in params), validate the email address.
|
||||
"""
|
||||
assert 'uidb64' in kwargs and 'token' in kwargs
|
||||
|
||||
self.validlink = False
|
||||
user = self.get_user(kwargs['uidb64'])
|
||||
token = kwargs['token']
|
||||
|
||||
# Validate the token
|
||||
if user is not None and email_validation_token.check_token(user, token):
|
||||
self.validlink = True
|
||||
user.registration.email_confirmed = True
|
||||
user.registration.save()
|
||||
return self.render_to_response(self.get_context_data(), status=200 if self.validlink else 400)
|
||||
|
||||
def get_user(self, uidb64):
|
||||
"""
|
||||
Get user from the base64-encoded string.
|
||||
"""
|
||||
try:
|
||||
# urlsafe_base64_decode() decodes to bytestring
|
||||
uid = urlsafe_base64_decode(uidb64).decode()
|
||||
user = User.objects.get(pk=uid)
|
||||
except (TypeError, ValueError, OverflowError, User.DoesNotExist, ValidationError):
|
||||
user = None
|
||||
return user
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['user_object'] = self.get_user(self.kwargs["uidb64"])
|
||||
context['login_url'] = resolve_url(settings.LOGIN_URL)
|
||||
if self.validlink:
|
||||
context['validlink'] = True
|
||||
else:
|
||||
context.update({
|
||||
'title': _('Email validation unsuccessful'),
|
||||
'validlink': False,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class UserValidationEmailSentView(TemplateView):
|
||||
"""
|
||||
Display the information that the validation link has been sent.
|
||||
"""
|
||||
template_name = 'registration/email_validation_email_sent.html'
|
||||
extra_context = dict(title=_('Email validation email sent'))
|
||||
|
||||
|
||||
class UserResendValidationEmailView(LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
Rensend the email validation link.
|
||||
"""
|
||||
model = User
|
||||
extra_context = dict(title=_("Resend email validation link"))
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user = self.get_object()
|
||||
user.registration.send_email_validation_link()
|
||||
return redirect('registration:email_validation_sent')
|
||||
|
||||
|
||||
class MyAccountDetailView(LoginRequiredMixin, RedirectView):
|
||||
"""
|
||||
Redirect to our own profile detail page.
|
||||
"""
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
return reverse_lazy("registration:user_detail", args=(self.request.user.pk,))
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
Display the detail about a user.
|
||||
"""
|
||||
|
||||
model = User
|
||||
context_object_name = "user_object"
|
||||
template_name = "registration/user_detail.html"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user = request.user
|
||||
if not user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
# Only an admin or the concerned user can see the information
|
||||
if not user.registration.is_admin and user.pk != kwargs["pk"]:
|
||||
raise PermissionDenied
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = _("Detail of user {user}").format(user=str(self.object.registration))
|
||||
return context
|
||||
|
||||
|
||||
class UserListView(AdminMixin, SingleTableView):
|
||||
"""
|
||||
Display the list of all registered users.
|
||||
"""
|
||||
model = Registration
|
||||
table_class = RegistrationTable
|
||||
template_name = "registration/user_list.html"
|
||||
|
||||
|
||||
class UserUpdateView(LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
Update the detail about a user and its registration.
|
||||
"""
|
||||
model = User
|
||||
form_class = UserForm
|
||||
template_name = "registration/update_user.html"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user = request.user
|
||||
if not user.registration.is_admin and user.pk != kwargs["pk"]:
|
||||
raise PermissionDenied
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
user = self.get_object()
|
||||
context["title"] = _("Update user {user}").format(user=str(self.object.registration))
|
||||
context["registration_form"] = user.registration.form_class(data=self.request.POST or None,
|
||||
instance=self.object.registration)
|
||||
if not user.registration.is_admin:
|
||||
if "team" in context["registration_form"].fields:
|
||||
del context["registration_form"].fields["team"]
|
||||
del context["registration_form"].fields["email_confirmed"]
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
user = form.instance
|
||||
registration_form = user.registration.form_class(data=self.request.POST or None,
|
||||
instance=self.object.registration)
|
||||
if not user.registration.is_admin:
|
||||
if "team" in registration_form.fields:
|
||||
del registration_form.fields["team"]
|
||||
del registration_form.fields["email_confirmed"]
|
||||
|
||||
if not registration_form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
|
||||
registration_form.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("registration:user_detail", args=(self.object.pk,))
|
||||
|
||||
|
||||
class UserUploadPhotoAuthorizationView(LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
A participant can send its photo authorization.
|
||||
"""
|
||||
model = StudentRegistration
|
||||
form_class = PhotoAuthorizationForm
|
||||
template_name = "registration/upload_photo_authorization.html"
|
||||
extra_context = dict(title=_("Upload photo authorization"))
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user = request.user
|
||||
if not user.registration.is_admin and user.registration.pk != kwargs["pk"]:
|
||||
raise PermissionDenied
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
old_instance = StudentRegistration.objects.get(pk=self.object.pk)
|
||||
if old_instance.photo_authorization:
|
||||
old_instance.photo_authorization.delete()
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
|
||||
|
||||
|
||||
class PhotoAuthorizationView(LoginRequiredMixin, View):
|
||||
"""
|
||||
Display the sent photo authorization.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
filename = kwargs["filename"]
|
||||
path = f"media/authorization/photo/{filename}"
|
||||
if not os.path.exists(path):
|
||||
raise Http404
|
||||
student = StudentRegistration.objects.get(photo_authorization__endswith=filename)
|
||||
user = request.user
|
||||
if not user.registration.is_admin and user.pk != student.user.pk:
|
||||
raise PermissionDenied
|
||||
# Guess mime type of the file
|
||||
mime = Magic(mime=True)
|
||||
mime_type = mime.from_file(path)
|
||||
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
||||
# Replace file name
|
||||
true_file_name = _("Photo authorization of {student}.{ext}").format(student=str(student), ext=ext)
|
||||
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
||||
|
||||
|
||||
class UserImpersonateView(LoginRequiredMixin, RedirectView):
|
||||
"""
|
||||
An administrator can log in through this page as someone else, and act as this other person.
|
||||
"""
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if self.request.user.registration.is_admin:
|
||||
if not User.objects.filter(pk=kwargs["pk"]).exists():
|
||||
raise Http404
|
||||
session = request.session
|
||||
session["admin"] = request.user.pk
|
||||
session["_fake_user_id"] = kwargs["pk"]
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
return reverse_lazy("registration:user_detail", args=(kwargs["pk"],))
|
||||
|
||||
|
||||
class ResetAdminView(LoginRequiredMixin, View):
|
||||
"""
|
||||
Return to admin view, clear the session field that let an administrator to log in as someone else.
|
||||
"""
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user = request.user
|
||||
if not user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if "_fake_user_id" in request.session:
|
||||
del request.session["_fake_user_id"]
|
||||
return redirect(request.GET.get("path", reverse_lazy("index")))
|
Reference in New Issue
Block a user