forked from DGNum/gestioCOF
Préparation Django2 : vues de login/logout
À partir de Django 2.1, les vues de login et logout sont class-based uniquement. On passe donc à django-cas-ng 2.6 pour harmoniser. On cleanup un peu le processus de login avec une classe un peu propre + un vrai formulaire/des vrais templates.
This commit is contained in:
parent
cef75e56d7
commit
a1ead1bfc8
6 changed files with 78 additions and 36 deletions
12
cof/urls.py
12
cof/urls.py
|
@ -49,10 +49,14 @@ urlpatterns = [
|
|||
TemplateView.as_view(template_name="cof-denied.html"),
|
||||
name="cof-denied",
|
||||
),
|
||||
url(r"^cas/login$", django_cas_views.login, name="cas_login_view"),
|
||||
url(r"^cas/logout$", django_cas_views.logout),
|
||||
url(r"^outsider/login$", gestioncof_views.login_ext, name="ext_login_view"),
|
||||
url(r"^outsider/logout$", django_views.logout, {"next_page": "home"}),
|
||||
url(r"^cas/login$", django_cas_views.LoginView.as_view(), name="cas_login_view"),
|
||||
url(r"^cas/logout$", django_cas_views.LogoutView.as_view()),
|
||||
url(
|
||||
r"^outsider/login$",
|
||||
gestioncof_views.LoginExtView.as_view(),
|
||||
name="ext_login_view",
|
||||
),
|
||||
url(r"^outsider/logout$", django_views.LogoutView.as_view(), {"next_page": "home"}),
|
||||
url(r"^login$", gestioncof_views.login, name="cof-login"),
|
||||
url(r"^logout$", gestioncof_views.logout, name="cof-logout"),
|
||||
# Infos persos
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.forms.formsets import BaseFormSet, formset_factory
|
||||
from django.forms.widgets import CheckboxSelectMultiple, RadioSelect
|
||||
|
@ -10,6 +11,37 @@ from gestioncof.models import CalendarSubscription, Club, CofProfile, EventComme
|
|||
from gestioncof.widgets import TriStateCheckbox
|
||||
|
||||
|
||||
class ExteAuthenticationForm(AuthenticationForm):
|
||||
"""
|
||||
Formulaire pour l'authentification des extés : renvoie une erreur si la personne
|
||||
qui essaie de s'authentifier n'a pas de mot de passe. L'erreur dépend de si la
|
||||
personne a un login clipper ou non.
|
||||
"""
|
||||
|
||||
def clean(self):
|
||||
username = self.cleaned_data.get("username")
|
||||
|
||||
if username is not None:
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
if not user.has_usable_password() or user.password in ("", "!"):
|
||||
profile, created = CofProfile.objects.get_or_create(user=user)
|
||||
if profile.login_clipper:
|
||||
raise forms.ValidationError(
|
||||
_("L'utilisateur·ice a un login clipper !"),
|
||||
code="has_clipper",
|
||||
)
|
||||
else:
|
||||
raise forms.ValidationError(
|
||||
_("L'utilisateur·ice n'a pas de mot de passe"),
|
||||
code="no_password",
|
||||
)
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
|
||||
return super().clean()
|
||||
|
||||
|
||||
class EventForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
event = kwargs.pop("event")
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
{% extends "base_title.html" %}
|
||||
|
||||
{% block realcontent %}
|
||||
{% if error_type == "use_clipper_login" %}
|
||||
{% if error_code == "has_clipper" %}
|
||||
<h2><strong>Votre identifiant est lié à un compte <tt>clipper</tt></strong></h2>
|
||||
<p>Veuillez vous connecter à l'aide de votre <a href="{% url 'cas_login_view' %}">compte <tt>clipper</tt></a></p>
|
||||
{% elif error_type == "no_password" %}
|
||||
{% elif error_code == "no_password" %}
|
||||
<h2><strong>Votre compte n'a pas de mot de passe associé</strong></h2>
|
||||
<p>Veuillez <a href="mailto:cof@clipper.ens.fr">nous contacter</a> pour que nous en définissions un et que nous vous le transmettions !</p>
|
||||
{% else %}
|
||||
<h1><strong>{{ error_title }}</strong></h1>
|
||||
<p>{{ error_description }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
7
gestioncof/templates/logout.html
Normal file
7
gestioncof/templates/logout.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% extends "base_title.html" %}
|
||||
|
||||
{% block realcontent %}
|
||||
<h2>
|
||||
Déconnexion réussie. À bientôt !
|
||||
</h2>
|
||||
{% endblock %}
|
|
@ -7,8 +7,8 @@ from django.contrib import messages
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.views import (
|
||||
login as django_login_view,
|
||||
logout as django_logout_view,
|
||||
LoginView as DjangoLoginView,
|
||||
LogoutView as DjangoLogoutView,
|
||||
redirect_to_login,
|
||||
)
|
||||
from django.contrib.sites.models import Site
|
||||
|
@ -18,7 +18,7 @@ from django.urls import reverse_lazy
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import FormView
|
||||
from django_cas_ng.views import logout as cas_logout_view
|
||||
from django_cas_ng.views import LogoutView as CasLogoutView
|
||||
from icalendar import Calendar, Event as Vevent
|
||||
|
||||
from bda.models import Spectacle, Tirage
|
||||
|
@ -29,6 +29,7 @@ from gestioncof.forms import (
|
|||
EventForm,
|
||||
EventFormset,
|
||||
EventStatusFilterForm,
|
||||
ExteAuthenticationForm,
|
||||
GestioncofConfigForm,
|
||||
ProfileForm,
|
||||
RegistrationPassUserForm,
|
||||
|
@ -81,26 +82,23 @@ def login(request):
|
|||
return render(request, "login_switch.html", context)
|
||||
|
||||
|
||||
def login_ext(request):
|
||||
if request.method == "POST" and "username" in request.POST:
|
||||
try:
|
||||
user = User.objects.get(username=request.POST["username"])
|
||||
if not user.has_usable_password() or user.password in ("", "!"):
|
||||
profile, created = CofProfile.objects.get_or_create(user=user)
|
||||
if profile.login_clipper:
|
||||
return render(
|
||||
request, "error.html", {"error_type": "use_clipper_login"}
|
||||
class LoginExtView(DjangoLoginView):
|
||||
template_name = "login.html"
|
||||
form_class = ExteAuthenticationForm
|
||||
|
||||
def form_invalid(self, form):
|
||||
# forms.non_field_errors() returns strings for some reason
|
||||
non_field_errors = form.errors["__all__"].as_data()
|
||||
exte_login_error = next(
|
||||
(e for e in non_field_errors if e.code in ["has_clipper", "no_password"]),
|
||||
None,
|
||||
)
|
||||
else:
|
||||
return render(request, "error.html", {"error_type": "no_password"})
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
context = {}
|
||||
if request.method == "GET" and "next" in request.GET:
|
||||
context["next"] = request.GET["next"]
|
||||
if request.method == "POST" and "next" in request.POST:
|
||||
context["next"] = request.POST["next"]
|
||||
return django_login_view(request, template_name="login.html", extra_context=context)
|
||||
|
||||
if exte_login_error is not None:
|
||||
return render(
|
||||
self.request, "login_error.html", {"error_code": exte_login_error.code}
|
||||
)
|
||||
return super().form_invalid(form)
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -112,13 +110,15 @@ def logout(request, next_page=None):
|
|||
|
||||
if profile and profile.login_clipper:
|
||||
msg = _("Déconnexion de GestioCOF et CAS réussie. À bientôt {}.")
|
||||
logout_view = cas_logout_view
|
||||
logout_view = CasLogoutView.as_view()
|
||||
else:
|
||||
msg = _("Déconnexion de GestioCOF réussie. À bientôt {}.")
|
||||
logout_view = django_logout_view
|
||||
logout_view = DjangoLogoutView.as_view(
|
||||
next_page=next_page, template_name="logout.html"
|
||||
)
|
||||
|
||||
messages.success(request, msg.format(request.user.get_short_name()))
|
||||
return logout_view(request, next_page=next_page)
|
||||
return logout_view(request)
|
||||
|
||||
|
||||
@login_required
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
configparser==3.5.0
|
||||
# TODO: change to 2.2 when out
|
||||
Django==1.11.*
|
||||
django-autocomplete-light==3.3.*
|
||||
django-autoslug==1.9.3
|
||||
django-cas-ng==3.5.*
|
||||
django-cas-ng==3.6.*
|
||||
django-djconfig==0.8.0
|
||||
django-recaptcha==1.4.0
|
||||
django-redis-cache==1.8.1
|
||||
|
@ -20,6 +21,7 @@ git+https://git.eleves.ens.fr/cof-geek/django_custommail.git#egg=django_customma
|
|||
ldap3
|
||||
channels==1.1.5
|
||||
python-dateutil
|
||||
# TODO: change to 2.5 when out (2.4 is not explicitly compatible with Django 2.2)
|
||||
wagtail==2.3.*
|
||||
wagtailmenus==2.12.*
|
||||
wagtail-modeltranslation==0.10.*
|
||||
|
|
Loading…
Reference in a new issue