]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Fix: handle allauth groups location breaking change (#11471)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Tue, 25 Nov 2025 17:18:05 +0000 (09:18 -0800)
committerGitHub <noreply@github.com>
Tue, 25 Nov 2025 17:18:05 +0000 (09:18 -0800)
src/paperless/signals.py
src/paperless/tests/test_signals.py

index a173ccc2e2987dc7718a0203b8e6c42987e4fd4f..cfad29dbd0446c971c75c202a16aa17dee18e876 100644 (file)
@@ -38,10 +38,19 @@ def handle_social_account_updated(sender, request, sociallogin, **kwargs):
     """
     from django.contrib.auth.models import Group
 
-    social_account_groups = sociallogin.account.extra_data.get(
+    extra_data = sociallogin.account.extra_data or {}
+    social_account_groups = extra_data.get(
         "groups",
         [],
-    )  # None if not found
+    )  # pre-allauth 65.11.0 structure
+
+    if not social_account_groups:
+        # allauth 65.11.0+ nests claims under `userinfo`/`id_token`
+        social_account_groups = (
+            extra_data.get("userinfo", {}).get("groups")
+            or extra_data.get("id_token", {}).get("groups")
+            or []
+        )
     if settings.SOCIAL_ACCOUNT_SYNC_GROUPS and social_account_groups is not None:
         groups = Group.objects.filter(name__in=social_account_groups)
         logger.debug(
index a77580b7bc803a7de4df8e901cce468ef20145d9..a21f3b6601e93e632dbccaca03d05a6c9621c43a 100644 (file)
@@ -192,6 +192,68 @@ class TestSyncSocialLoginGroups(TestCase):
         )
         self.assertEqual(list(user.groups.all()), [])
 
+    @override_settings(SOCIAL_ACCOUNT_SYNC_GROUPS=True)
+    def test_userinfo_groups(self):
+        """
+        GIVEN:
+            - Enabled group syncing, and `groups` nested under `userinfo`
+        WHEN:
+            - The social login is updated via signal after login
+        THEN:
+            - The user's groups are updated using `userinfo.groups`
+        """
+        group = Group.objects.create(name="group1")
+        user = User.objects.create_user(username="testuser")
+        sociallogin = Mock(
+            user=user,
+            account=Mock(
+                extra_data={
+                    "userinfo": {
+                        "groups": ["group1"],
+                    },
+                },
+            ),
+        )
+
+        handle_social_account_updated(
+            sender=None,
+            request=HttpRequest(),
+            sociallogin=sociallogin,
+        )
+
+        self.assertEqual(list(user.groups.all()), [group])
+
+    @override_settings(SOCIAL_ACCOUNT_SYNC_GROUPS=True)
+    def test_id_token_groups_fallback(self):
+        """
+        GIVEN:
+            - Enabled group syncing, and `groups` only under `id_token`
+        WHEN:
+            - The social login is updated via signal after login
+        THEN:
+            - The user's groups are updated using `id_token.groups`
+        """
+        group = Group.objects.create(name="group1")
+        user = User.objects.create_user(username="testuser")
+        sociallogin = Mock(
+            user=user,
+            account=Mock(
+                extra_data={
+                    "id_token": {
+                        "groups": ["group1"],
+                    },
+                },
+            ),
+        )
+
+        handle_social_account_updated(
+            sender=None,
+            request=HttpRequest(),
+            sociallogin=sociallogin,
+        )
+
+        self.assertEqual(list(user.groups.all()), [group])
+
 
 class TestUserGroupDeletionCleanup(TestCase):
     """