Merge branch 'kerl/class_based_views' into 'master'

Réécrit les vues d'auth sous forme de class-based-views

Closes #3

See merge request klub-dev-ens/authens!3
This commit is contained in:
Ludovic Stephan 2020-05-13 20:33:00 +02:00
commit 470bca4d1f
3 changed files with 69 additions and 50 deletions

View file

@ -7,10 +7,10 @@
<title>ENS Auth</title>
</head>
<body>
<p><a href="{% url "authens:login.cas" %}?next={{ next | urlencode }}">
<p><a href="{% url "authens:login.cas" %}?next={{ next| urlencode }}">
{% trans "Login par CAS" %}
</a></p>
<p><a href="{% url "authens:login.pwd" %}?next={{ next | urlencode }}">
<p><a href="{% url "authens:login.pwd" %}?next={{ next| urlencode }}">
{% trans "Login par mot de passe" %}
</a></p>
</body>

View file

@ -5,8 +5,8 @@ from authens import views
app_name = "authens"
urlpatterns = [
path("login/choose", views.login_switch, name="login"),
path("login/cas", views.cas_login, name="login.cas"),
path("login/pwd", views.pwd_login, name="login.pwd"),
path("login/choose", views.LoginSwitchView.as_view(), name="login"),
path("login/cas", views.CASLoginView.as_view(), name="login.cas"),
path("login/pwd", views.PasswordLoginView.as_view(), name="login.pwd"),
path("logout", auth_views.LogoutView.as_view(), name="logout"),
]

View file

@ -1,57 +1,76 @@
from django.conf import settings
from django.contrib import auth
from django.core.exceptions import PermissionDenied
from django.views.decorators.http import require_GET
from django.shortcuts import redirect, render
from django.views.generic import TemplateView, View
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from authens.utils import get_cas_client
def _get_next_url(request):
"""Decide where to go after a successful login.
class NextPageMixin:
def get_next_url(self):
"""Decide where to go after a successful login.
Look for (in order):
- a `next` GET parameter;
- a `CASNEXT` session variable;
- the `LOGIN_REDIRECT_URL` django setting.
Look for (in order):
- a `next` GET parameter;
- a `CASNEXT` session variable;
- the `LOGIN_REDIRECT_URL` django setting.
"""
request = self.request
next_url = request.GET.get("next")
if next_url is None and "CASNEXT" in request.session:
next_url = request.session["CASNEXT"]
del request.session["CASNEXT"]
if next_url is None:
next_url = settings.LOGIN_REDIRECT_URL
return next_url
class LoginSwitchView(NextPageMixin, TemplateView):
"""Simple page letting the user choose between password and CAS authentication."""
template_name = "authens/login_switch.html"
http_method_names = ["get"]
def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect(self.get_next_url())
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx["next"] = self.get_next_url()
return ctx
class CASLoginView(NextPageMixin, View):
"""CAS authentication view.
Implement the CAS authentication scheme:
1. We first redirect the user to the student CAS.
2. The user comes back with a ticket, we validate it to make sure the user is legit
(validation is delegated to the ENSCASBackend).
3. We redirect the user to the next page.
"""
next_page = request.GET.get("next")
if next_page is None and "CASNEXT" in request.session:
next_page = request.session["CASNEXT"]
del request.session["CASNEXT"]
if next_page is None:
next_page = settings.LOGIN_REDIRECT_URL
return next_page
http_method_names = ["get"]
def get(self, request, *args, **kwargs):
ticket = request.GET.get("ticket")
if not ticket:
request.session["CASNEXT"] = self.get_next_url()
cas_client = get_cas_client(request)
return redirect(cas_client.get_login_url())
user = auth.authenticate(request, ticket=ticket)
if user is None:
raise PermissionDenied(_("Connection échouée !"))
auth.login(request, user)
return redirect(self.get_next_url())
@require_GET
def login_switch(request):
next_page = _get_next_url(request)
if request.user.is_authenticated:
return redirect(next_page)
return render(request, "authens/login_switch.html", {"next": next_page})
@require_GET
def cas_login(request):
next_page = _get_next_url(request)
ticket = request.GET.get("ticket")
# User's request: redirect the user to cas.eleves
if not ticket:
request.session["CASNEXT"] = next_page # remember next_page
cas_client = get_cas_client(request)
return redirect(cas_client.get_login_url())
# CAS' request: validate the ticket
user = auth.authenticate(request, ticket=ticket)
if user is None:
raise PermissionDenied(_("Connection échouée !"))
# Success: log the user in
auth.login(request, user)
return redirect(next_page)
pwd_login = auth.views.LoginView.as_view(template_name="authens/pwd_login.html")
class PasswordLoginView(auth.views.LoginView):
template_name = "authens/pwd_login.html"