diff --git a/allauth_ens/adapter.py b/allauth_ens/adapter.py index 662c98a..c68a5bf 100644 --- a/allauth_ens/adapter.py +++ b/allauth_ens/adapter.py @@ -147,14 +147,20 @@ def deprecate_clippers(): clippers.update(provider='clipper_inactive') -def install_longterm_adapter(fake=False): +def install_longterm_adapter(fake=False, accounts=None): """ Manages the transition from an older django_cas or an allauth_ens installation without LongTermClipperAccountAdapter + + accounts is an optional dictionary containing the association between + clipper usernames and django's User accounts. If not provided, the + function will assumer Users' usernames are their clipper uid. """ - accounts = {u.username: u for u in User.objects.all() - if u.username.isalnum()} + if accounts is None: + accounts = {u.username: u for u in User.objects.all() + if u.username.isalnum()} + ldap_connection = init_ldap() ltc_adapter = get_adapter() diff --git a/allauth_ens/management/commands/install_longterm.py b/allauth_ens/management/commands/install_longterm.py index 40ccde3..40cc988 100644 --- a/allauth_ens/management/commands/install_longterm.py +++ b/allauth_ens/management/commands/install_longterm.py @@ -1,6 +1,9 @@ # coding: utf-8 +from django.contrib.auth import get_user_model from django.core.management.base import BaseCommand +from allauth.socialaccount.models import SocialAccount + from allauth_ens.adapter import install_longterm_adapter @@ -17,10 +20,43 @@ class Command(BaseCommand): help=('Does not save the models created/updated,' 'only shows the list'), ) + parser.add_argument( + '--use-socialaccounts', + action='store_true', + default=False, + help=('Use the existing SocialAccounts rather than all the Users'), + ) + parser.add_argument( + '--clipper-field', + default=None, + type=str + ) pass def handle(self, *args, **options): - logs = install_longterm_adapter(options.get("fake", False)) + fake = options.get("fake", False) + + if options.get('use_socialaccounts', False): + accounts = {account.uid: account.user for account in + (SocialAccount.objects.filter(provider="clipper") + .prefetch_related("user"))} + elif options.get('clipper_field', None): + fields = options['clipper_field'].split('.') + User = get_user_model() + + def get_subattr(obj, fields): + # Allows to follow OneToOne relationships + if len(fields) == 1: + return getattr(obj, fields[0]) + return get_subattr(getattr(obj, fields[0]), fields[1:]) + + accounts = {get_subattr(account, fields): account for account in + User.objects.all()} + else: + accounts = None + + logs = install_longterm_adapter(fake, accounts) + self.stdout.write("Social accounts created : %d" % len(logs["created"])) self.stdout.write(" ".join(("%s -> %s" % s) for s in logs["created"])) diff --git a/allauth_ens/tests.py b/allauth_ens/tests.py index a35ca3b..a7afe33 100644 --- a/allauth_ens/tests.py +++ b/allauth_ens/tests.py @@ -7,6 +7,7 @@ from django.contrib.auth import HASH_SESSION_KEY, get_user_model from django.contrib.sites.models import Site from django.core import mail from django.test import TestCase, override_settings +from django.test.utils import captured_stdout from allauth.socialaccount.models import SocialAccount @@ -18,6 +19,7 @@ from mock import patch from allauth_ens.utils import get_ldap_infos from .adapter import deprecate_clippers, install_longterm_adapter +from .management.commands.install_longterm import Command as InstallLongterm _mock_ldap = MockLDAP() ldap_patcher = patch('allauth_ens.utils.ldap.initialize', @@ -331,6 +333,69 @@ class LongTermClipperTests(CASTestCase): self.assertEqual(user1.username, "test@12") self.assertEqual(conn.extra_data['ldap']['entrance_year'], '12') + def test_longterm_installer_from_allauth_command_username(self): + self._setup_ldap(12) + with self.settings( + SOCIALACCOUNT_ADAPTER='allauth.socialaccount.' + 'adapter.DefaultSocialAccountAdapter'): + r = self.client_cas_login(self.client, provider_id="clipper", + username='test') + user0 = r.context["user"] + nsa0 = SocialAccount.objects.count() + self.assertEqual(user0.username, "test") + self.client.logout() + + with captured_stdout() as stdout: + command = InstallLongterm() + command.handle(clipper_field='username') + + output = stdout.getvalue() + self.assertIn('test -> test@12', output) + + r = self.client_cas_login(self.client, provider_id="clipper", + username='test') + user1 = r.context["user"] + nsa1 = SocialAccount.objects.count() + conn = user1.socialaccount_set.get(provider='clipper') + self.assertEqual(user1.id, user0.id) + self.assertEqual(nsa1, nsa0) + self.assertEqual(user1.username, "test@12") + self.assertEqual(conn.extra_data['ldap']['entrance_year'], '12') + + def test_longterm_installer_from_allauth_command_socialaccounts(self): + self._setup_ldap(12) + with self.settings( + SOCIALACCOUNT_ADAPTER='allauth.socialaccount.' + 'adapter.DefaultSocialAccountAdapter'): + r = self.client_cas_login(self.client, provider_id="clipper", + username='test') + user0 = r.context["user"] + self.assertEqual(user0.username, "test") + self.client.logout() + + user1 = User.objects.create_user('bidule', 'bidule@clipper.ens.fr', + 'bidule') + nsa0 = SocialAccount.objects.count() + + with captured_stdout() as stdout: + command = InstallLongterm() + command.handle(use_socialaccounts=True) + + output = stdout.getvalue() + self.assertIn('test -> test@12', output) + self.assertNotIn('bidule ->', output) + + r = self.client_cas_login(self.client, provider_id="clipper", + username='test') + user1 = r.context["user"] + nsa1 = SocialAccount.objects.count() + conn = user1.socialaccount_set.get(provider='clipper') + self.assertEqual(user1.id, user0.id) + self.assertEqual(nsa1, nsa0) + self.assertEqual(nsa1, nsa0) + self.assertEqual(user1.username, "test@12") + self.assertEqual(conn.extra_data['ldap']['entrance_year'], '12') + def test_longterm_installer_from_djangocas(self): with self.settings( SOCIALACCOUNT_ADAPTER='allauth.socialaccount.'