diff --git a/authens/backends.py b/authens/backends.py index 6033aad..40080ac 100644 --- a/authens/backends.py +++ b/authens/backends.py @@ -60,7 +60,10 @@ class ENSCASBackend: cas_login = self.clean_cas_login(cas_login) year = get_entrance_year(attributes) - return self._get_or_create(cas_login, year) + user = self._get_or_create(cas_login, year) + user.cas_account.connected_to_cas = True + user.cas_account.save() + return user def clean_cas_login(self, cas_login): return cas_login.strip().lower() diff --git a/authens/migrations/0002_casaccount_connected_to_cas.py b/authens/migrations/0002_casaccount_connected_to_cas.py new file mode 100644 index 0000000..84910a3 --- /dev/null +++ b/authens/migrations/0002_casaccount_connected_to_cas.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.6 on 2020-05-17 12:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authens', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='casaccount', + name='connected_to_cas', + field=models.BooleanField(default=False, editable=False), + ), + ] diff --git a/authens/models.py b/authens/models.py index 90b107c..01699fd 100644 --- a/authens/models.py +++ b/authens/models.py @@ -27,6 +27,11 @@ class CASAccount(models.Model): verbose_name=_("année de création du compte CAS"), blank=False, null=False ) + # This is True if and only if the user is connected via CAS (and not e.g. by + # password). This is used to decide whether to redirect to user to the CAS logout + # page or not when the user disconnects. + connected_to_cas = models.BooleanField(default=False, editable=False) + class Meta: verbose_name = _("Compte CAS") verbose_name_plural = _("Comptes CAS") diff --git a/authens/urls.py b/authens/urls.py index f28100f..7b13310 100644 --- a/authens/urls.py +++ b/authens/urls.py @@ -1,4 +1,3 @@ -from django.contrib.auth import views as auth_views from django.urls import path from authens import views @@ -8,5 +7,5 @@ urlpatterns = [ 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"), + path("logout", views.LogoutView.as_view(), name="logout"), ] diff --git a/authens/views.py b/authens/views.py index 06b80d5..58152a0 100644 --- a/authens/views.py +++ b/authens/views.py @@ -1,10 +1,12 @@ from django.conf import settings from django.contrib import auth +from django.contrib.auth import views as auth_views from django.core.exceptions import PermissionDenied from django.views.generic import TemplateView, View from django.shortcuts import redirect from django.utils.translation import gettext_lazy as _ +from authens.models import CASAccount from authens.utils import get_cas_client @@ -72,5 +74,27 @@ class CASLoginView(NextPageMixin, View): return redirect(self.get_next_url()) -class PasswordLoginView(auth.views.LoginView): +class PasswordLoginView(auth_views.LoginView): template_name = "authens/pwd_login.html" + + +class LogoutView(auth_views.LogoutView): + """Logout view of AuthENS. + + Tell Django to log the user out, then redirect to the CAS logout page if the user + logged in via CAS. + """ + + def setup(self, *args, **kwargs): + super().setup(*args, **kwargs) + cas_account = CASAccount.objects.filter(user=self.request.user) + self.cas_account = cas_account.get() if cas_account.exists() else None + + def get_next_page(self): + if self.cas_account and self.cas_account.connected_to_cas: + cas_client = get_cas_client(self.request) + self.cas_account.connected_to_cas = False + self.cas_account.save() + return cas_client.get_logout_url() + else: + return super().get_next_page()