From 79eb294ce572ab3944bfcf2782fc267b3aad572f Mon Sep 17 00:00:00 2001 From: Robin Champenois Date: Sun, 17 Jan 2021 21:15:52 +0100 Subject: [PATCH] AuthENS : migration depuis allauth --- README.md | 2 +- avisstage/admin.py | 5 + .../migrations/0004_allauth_to_authens.py | 93 +++++++++++++++++++ avisstage/templates/avisstage/base.html | 4 +- avisstage/templates/avisstage/index.html | 4 +- experiENS/settings_base.py | 7 +- experiENS/settings_dev.py | 2 +- experiENS/urls.py | 2 + 8 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 avisstage/migrations/0004_allauth_to_authens.py diff --git a/README.md b/README.md index 93536c0..ba23394 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Il est visible sur https://www.eleves.ens.fr/experiens/ Clonez le dépôt. Installez les pré-requis : - sudo apt-get install libxlst-dev python3.4-dev + sudo apt-get install libxlst-dev libsals2-dev libxml2-dev libldap2-dev libssl-dev On a besoin de SpatiaLite pour une base de données GIS. Essayez diff --git a/avisstage/admin.py b/avisstage/admin.py index 5d3581a..c57f678 100644 --- a/avisstage/admin.py +++ b/avisstage/admin.py @@ -3,6 +3,8 @@ from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User from avisstage.models import * +import authens.models as authmod + class NormalienInline(admin.StackedInline): model = Normalien inline_classes = ("collapse open",) @@ -32,3 +34,6 @@ admin.site.register(User, UserAdmin) admin.site.register(Lieu) admin.site.register(StageMatiere, StageMatiereAdmin) admin.site.register(Stage, StageAdmin) + +admin.site.register(authmod.CASAccount) +admin.site.register(authmod.OldCASAccount) diff --git a/avisstage/migrations/0004_allauth_to_authens.py b/avisstage/migrations/0004_allauth_to_authens.py new file mode 100644 index 0000000..0693a74 --- /dev/null +++ b/avisstage/migrations/0004_allauth_to_authens.py @@ -0,0 +1,93 @@ +from django.apps import apps as global_apps +from django.db import migrations + +def forwards(apps, schema_editor): + User = apps.get_model('auth', 'User') + + try: + CASAccount = apps.get_model('authens', 'CASAccount') + except LookupError: + return + + try: + SocialAccount = apps.get_model('socialaccount', 'SocialAccount') + EmailAddress = apps.get_model('account', 'EmailAddress') + except LookupError: + # Allauth not installed + # Simply create CAS accounts for every profile + # This procedure is not meant to be fast + from authens.shortcuts import fetch_cas_account + + def migrate_user(user): + ldap_info = fetch_cas_account(user.username) + if ldap_info: + entrance_year = ldap_info["entrance_year"] + CASAccount.objects.create( + user=user, cas_login=user.username, + entrance_year=entrance_year + ) + + for user in User.objects.all(): + migrate_user(user) + return + + # Transfer from allauth to authens + # Assumes usernames have the format @ + # Assumes no clashing clipper accounts have ever been found + oldusers = ( + User.objects.all().prefetch_related( + "emailaddress_set", "socialaccount_set") + ) + + is_ens_mail = lambda mail: ( + mail is not None and (mail.endswith(".ens.fr") or mail.endswith(".ens.psl.eu"))) + new_conns = [] + + for user in oldusers: + # Sanitize mail addresses + addresses = user.emailaddress_set.all() + if len(addresses) > 0: + email = user.email + is_email_ens = is_ens_mail(email) + for address in addresses: + if is_ens_mail(address.email): + if email is None: + email = address.email + is_email_ens = True + continue + if address.primary or email is None or is_email_ens: + email = address.email + is_email_ens = False + if email != user.email: + user.email = email + user.save() + + # Create new CASAccount connexion + saccounts = user.socialaccount_set.all() + if not saccounts: + continue + if len(saccounts) > 1: + print(saccounts) + saccount = saccounts[0] + clipper = saccount.uid + if "@" not in user.username: + print(saccount) + continue + entrance_year = "20" + saccount.extra_data.get( + "entrance_year", user.username.split("@")[1]) + new_conns.append(CASAccount(user=user, cas_login=clipper, + entrance_year=int(entrance_year))) + + CASAccount.objects.bulk_create(new_conns) + +class Migration(migrations.Migration): + operations = [ + migrations.RunPython(forwards, migrations.RunPython.noop), + ] + dependencies = [ + ('avisstage', '0003_auto_20210117_1208'), + ('authens', '0002_old_cas_account'), + ] + + if global_apps.is_installed('allauth'): + dependencies.append(('socialaccount', '0003_extra_data_default_dict')) diff --git a/avisstage/templates/avisstage/base.html b/avisstage/templates/avisstage/base.html index 33eda80..1bd1ced 100644 --- a/avisstage/templates/avisstage/base.html +++ b/avisstage/templates/avisstage/base.html @@ -37,9 +37,9 @@
  • Modo
  • {% endif %} {% if user.is_authenticated %} -
  • {{ user.username }}
    Déconnexion
  • +
  • {{ user.username }}
    Déconnexion
  • {% else %} -
  • Connexion
  • +
  • Connexion
  • {% endif %} diff --git a/avisstage/templates/avisstage/index.html b/avisstage/templates/avisstage/index.html index a7d664b..f9c20da 100644 --- a/avisstage/templates/avisstage/index.html +++ b/avisstage/templates/avisstage/index.html @@ -11,9 +11,9 @@ {% if not user.is_authenticated %}
    -

    Connexion

    +

    Connexion

    Connexion via le serveur central d'authentification ENS
    (identifiants clipper)

    -

    Accès archicubes
    Pour continuer à tenir à jour ses fiches, sans voir celles des autres

    +

    Accès archicubes
    Pour continuer à tenir à jour ses fiches, sans voir celles des autres

    {% endif %} diff --git a/experiENS/settings_base.py b/experiENS/settings_base.py index f1729cf..0962539 100644 --- a/experiENS/settings_base.py +++ b/experiENS/settings_base.py @@ -45,6 +45,7 @@ INSTALLED_APPS = [ 'allauth_ens.providers.clipper', + 'authens', 'tastypie', 'braces', 'tinymce', @@ -117,7 +118,7 @@ STATIC_URL = '/static/' AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', - 'experiENS.auth.ENSCASBackend', + 'authens.backends.ENSCASBackend', ) CAS_SERVER_URL = "https://cas.eleves.ens.fr/" #SPI CAS @@ -131,8 +132,8 @@ CAS_VERSION = 'CAS_2_SAML_1_0' ACCOUNT_ADAPTER = 'avisstage.allauth_adapter.AccountAdapter' SOCIALACCOUNT_ADAPTER = 'avisstage.allauth_adapter.SocialAccountAdapter' -LOGIN_URL = reverse_lazy('account_login') -LOGOUT_URL = reverse_lazy('account_logout') +LOGIN_URL = reverse_lazy('authens:login') +LOGOUT_URL = reverse_lazy('authens:logout') LOGIN_REDIRECT_URL = reverse_lazy('avisstage:perso') ACCOUNT_HOME_URL = reverse_lazy('avisstage:index') diff --git a/experiENS/settings_dev.py b/experiENS/settings_dev.py index e7fbc37..e031652 100644 --- a/experiENS/settings_dev.py +++ b/experiENS/settings_dev.py @@ -22,7 +22,7 @@ if USE_DEBUG_TOOLBAR: INTERNAL_IPS = ['127.0.0.1'] -SPATIALITE_LIBRARY_PATH = 'mod_spatialite.so' +SPATIALITE_LIBRARY_PATH = 'mod_spatialite' STATIC_ROOT = "/home/evarin/Bureau/experiENS/static/" diff --git a/experiENS/urls.py b/experiENS/urls.py index 5fd072d..4a8e6f7 100644 --- a/experiENS/urls.py +++ b/experiENS/urls.py @@ -5,6 +5,8 @@ from django.contrib import admin urlpatterns = [ path('', include('avisstage.urls')), + + path("authens/", include("authens.urls")), path('account/', include('allauth_ens.urls')), path('tinymce/', include('tinymce.urls')),