AuthENS : migration depuis allauth

This commit is contained in:
Robin Champenois 2021-01-17 21:15:52 +01:00
parent 72f28d185c
commit 79eb294ce5
8 changed files with 110 additions and 9 deletions

View file

@ -9,7 +9,7 @@ Il est visible sur https://www.eleves.ens.fr/experiens/
Clonez le dépôt. Installez les pré-requis : 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 On a besoin de SpatiaLite pour une base de données GIS. Essayez

View file

@ -3,6 +3,8 @@ from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User from django.contrib.auth.models import User
from avisstage.models import * from avisstage.models import *
import authens.models as authmod
class NormalienInline(admin.StackedInline): class NormalienInline(admin.StackedInline):
model = Normalien model = Normalien
inline_classes = ("collapse open",) inline_classes = ("collapse open",)
@ -32,3 +34,6 @@ admin.site.register(User, UserAdmin)
admin.site.register(Lieu) admin.site.register(Lieu)
admin.site.register(StageMatiere, StageMatiereAdmin) admin.site.register(StageMatiere, StageMatiereAdmin)
admin.site.register(Stage, StageAdmin) admin.site.register(Stage, StageAdmin)
admin.site.register(authmod.CASAccount)
admin.site.register(authmod.OldCASAccount)

View file

@ -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 <clipper>@<promo>
# 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'))

View file

@ -37,9 +37,9 @@
<li><a href="{% url 'avisstage:moderation' %}">Modo</a></li> <li><a href="{% url 'avisstage:moderation' %}">Modo</a></li>
{% endif %} {% endif %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<li><a href="{% url "account_logout" %}"><span class="username">{{ user.username }}</span><br/> Déconnexion</a></li> <li><a href="{% url "authens:logout" %}"><span class="username">{{ user.username }}</span><br/> Déconnexion</a></li>
{% else %} {% else %}
<li><a href="{% url "account_login" %}">Connexion</a></li> <li><a href="{% url "authens:login" %}">Connexion</a></li>
{% endif %} {% endif %}
</ul> </ul>
</nav> </nav>

View file

@ -11,9 +11,9 @@
{% if not user.is_authenticated %} {% if not user.is_authenticated %}
<div class="entrer"> <div class="entrer">
<p><a href="{% url "clipper_login" %}" class="btn">Connexion</a></p> <p><a href="{% url "authens:login.cas" %}" class="btn">Connexion</a></p>
<p class="helptext">Connexion via le serveur central d'authentification ENS <br />(identifiants clipper)</p> <p class="helptext">Connexion via le serveur central d'authentification ENS <br />(identifiants clipper)</p>
<p class="archicubes"><a href="{% url "account_login" %}">Accès archicubes</a> <br /><i>Pour continuer à tenir à jour ses fiches, sans voir celles des autres</i></p> <p class="archicubes"><a href="{% url "authens:login.pwd" %}">Accès archicubes</a> <br /><i>Pour continuer à tenir à jour ses fiches, sans voir celles des autres</i></p>
</div> </div>
{% endif %} {% endif %}

View file

@ -45,6 +45,7 @@ INSTALLED_APPS = [
'allauth_ens.providers.clipper', 'allauth_ens.providers.clipper',
'authens',
'tastypie', 'tastypie',
'braces', 'braces',
'tinymce', 'tinymce',
@ -117,7 +118,7 @@ STATIC_URL = '/static/'
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', 'django.contrib.auth.backends.ModelBackend',
'experiENS.auth.ENSCASBackend', 'authens.backends.ENSCASBackend',
) )
CAS_SERVER_URL = "https://cas.eleves.ens.fr/" #SPI CAS 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' ACCOUNT_ADAPTER = 'avisstage.allauth_adapter.AccountAdapter'
SOCIALACCOUNT_ADAPTER = 'avisstage.allauth_adapter.SocialAccountAdapter' SOCIALACCOUNT_ADAPTER = 'avisstage.allauth_adapter.SocialAccountAdapter'
LOGIN_URL = reverse_lazy('account_login') LOGIN_URL = reverse_lazy('authens:login')
LOGOUT_URL = reverse_lazy('account_logout') LOGOUT_URL = reverse_lazy('authens:logout')
LOGIN_REDIRECT_URL = reverse_lazy('avisstage:perso') LOGIN_REDIRECT_URL = reverse_lazy('avisstage:perso')
ACCOUNT_HOME_URL = reverse_lazy('avisstage:index') ACCOUNT_HOME_URL = reverse_lazy('avisstage:index')

View file

@ -22,7 +22,7 @@ if USE_DEBUG_TOOLBAR:
INTERNAL_IPS = ['127.0.0.1'] INTERNAL_IPS = ['127.0.0.1']
SPATIALITE_LIBRARY_PATH = 'mod_spatialite.so' SPATIALITE_LIBRARY_PATH = 'mod_spatialite'
STATIC_ROOT = "/home/evarin/Bureau/experiENS/static/" STATIC_ROOT = "/home/evarin/Bureau/experiENS/static/"

View file

@ -5,6 +5,8 @@ from django.contrib import admin
urlpatterns = [ urlpatterns = [
path('', include('avisstage.urls')), path('', include('avisstage.urls')),
path("authens/", include("authens.urls")),
path('account/', include('allauth_ens.urls')), path('account/', include('allauth_ens.urls')),
path('tinymce/', include('tinymce.urls')), path('tinymce/', include('tinymce.urls')),