Use class-based views rather than functions
This commit is contained in:
parent
add3b56690
commit
e3c3513a21
3 changed files with 70 additions and 50 deletions
|
@ -7,10 +7,10 @@
|
||||||
<title>ENS Auth</title>
|
<title>ENS Auth</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p><a href="{% url "authens:login.cas" %}?next={{ next | urlencode }}">
|
<p><a href="{% url "authens:login.cas" %}?next={{ next_page | urlencode }}">
|
||||||
{% trans "Login par CAS" %}
|
{% trans "Login par CAS" %}
|
||||||
</a></p>
|
</a></p>
|
||||||
<p><a href="{% url "authens:login.pwd" %}?next={{ next | urlencode }}">
|
<p><a href="{% url "authens:login.pwd" %}?next={{ next_page | urlencode }}">
|
||||||
{% trans "Login par mot de passe" %}
|
{% trans "Login par mot de passe" %}
|
||||||
</a></p>
|
</a></p>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -5,8 +5,8 @@ from authens import views
|
||||||
|
|
||||||
app_name = "authens"
|
app_name = "authens"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("login/choose", views.login_switch, name="login"),
|
path("login/choose", views.LoginSwitchView.as_view(), name="login"),
|
||||||
path("login/cas", views.cas_login, name="login.cas"),
|
path("login/cas", views.CASLoginView.as_view(), name="login.cas"),
|
||||||
path("login/pwd", views.pwd_login, name="login.pwd"),
|
path("login/pwd", views.PasswordLoginView.as_view(), name="login.pwd"),
|
||||||
path("logout", auth_views.LogoutView.as_view(), name="logout"),
|
path("logout", auth_views.LogoutView.as_view(), name="logout"),
|
||||||
]
|
]
|
||||||
|
|
110
authens/views.py
110
authens/views.py
|
@ -1,57 +1,77 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.views.decorators.http import require_GET
|
from django.views.generic import RedirectView, TemplateView
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from authens.utils import get_cas_client
|
from authens.utils import get_cas_client
|
||||||
|
|
||||||
|
|
||||||
def _get_next_url(request):
|
class NextPageMixin:
|
||||||
"""Decide where to go after a successful login.
|
def next_page_url(self):
|
||||||
|
"""Decide where to go after a successful login.
|
||||||
|
|
||||||
Look for (in order):
|
Look for (in order):
|
||||||
- a `next` GET parameter;
|
- a `next` GET parameter;
|
||||||
- a `CASNEXT` session variable;
|
- a `CASNEXT` session variable;
|
||||||
- the `LOGIN_REDIRECT_URL` django setting.
|
- the `LOGIN_REDIRECT_URL` django setting.
|
||||||
|
"""
|
||||||
|
request = self.request
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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.next_page_url())
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
ctx["next_page"] = self.next_page_url()
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
class CASLoginView(NextPageMixin, RedirectView):
|
||||||
|
"""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:
|
http_method_names = ["get"]
|
||||||
next_page = request.session["CASNEXT"]
|
|
||||||
del request.session["CASNEXT"]
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
if next_page is None:
|
request = self.request
|
||||||
next_page = settings.LOGIN_REDIRECT_URL
|
ticket = request.GET.get("ticket")
|
||||||
return next_page
|
|
||||||
|
if not ticket:
|
||||||
|
request.session["CASNEXT"] = self.next_page_url()
|
||||||
|
cas_client = get_cas_client(request)
|
||||||
|
return 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 self.next_page_url()
|
||||||
|
|
||||||
|
|
||||||
@require_GET
|
class PasswordLoginView(auth.views.LoginView):
|
||||||
def login_switch(request):
|
template_name = "authens/pwd_login.html"
|
||||||
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")
|
|
||||||
|
|
Loading…
Reference in a new issue