Repository: pennersr/django-allauth

Issue:
About user_logged_out signal
Hi everyone,

Using the default account adapter, allauth [sends](https://github.com/pennersr/django-allauth/blob/81af6a54be579a565b3eef1766642cbaca7ee5a3/allauth/account/adapter.py#L395) the ``allauth.account.signal.user_logged_out`` signal on logout. But this signal is sent after the call to the classical django' logout function. So it misses a few things, e.g. `request.session` has already been flushed when this signal is emitted.

Maybe the docs could:
- specify when the signal is sent, i.e. at the (very) end of the logout flow,
- say [`django.contrib.auth.signals.user_logged_out`](https://docs.djangoproject.com/en/dev/ref/contrib/auth/#django.contrib.auth.signals.user_logged_out) is still sent on logout. This signal is sent earlier in the logout flow, such as listeners can still accessed the content of `request.session` before it has been flushed.

Just to say, initially i was doubting this signal (allauth' one) is worthwhile, because it seems like a messier copy of the django' one. But in fact they provide multiple listening points in the logout flow, namingly pre/post logout. With django' signal, you can access the session before it has been flushed, but it's useless to set session value. With allauth' one, session will be empty, but you can set session values and they will be kept. So "why not".


Discussion:
True, this is confusing... allauth should be compliant to the behavior of the Django signal.

Resolving patch:
diff --git a/allauth/account/adapter.py b/allauth/account/adapter.py
--- a/allauth/account/adapter.py
+++ b/allauth/account/adapter.py
@@ -33,7 +33,6 @@
     get_user_model,
     import_attribute,
 )
-from .signals import user_logged_out
 
 
 try:
@@ -389,12 +388,7 @@ def login(self, request, user):
         django_login(request, user)
 
     def logout(self, request):
-        user = request.user
         django_logout(request)
-        user_logged_out.send(
-            sender=user.__class__,
-            request=request,
-            user=user)
 
     def confirm_email(self, request, email_address):
         """
diff --git a/allauth/account/signals.py b/allauth/account/signals.py
--- a/allauth/account/signals.py
+++ b/allauth/account/signals.py
@@ -1,8 +1,8 @@
+from django.contrib.auth.signals import user_logged_out  # noqa
 from django.dispatch import Signal
 
 
 user_logged_in = Signal(providing_args=["request", "user"])
-user_logged_out = Signal(providing_args=["request", "user"])
 
 # Typically followed by `user_logged_in` (unless, e-mail verification kicks in)
 user_signed_up = Signal(providing_args=["request", "user"])


Test patch:
diff --git a/allauth/account/tests.py b/allauth/account/tests.py
--- a/allauth/account/tests.py
+++ b/allauth/account/tests.py
@@ -22,13 +22,14 @@
     EmailConfirmation,
     EmailConfirmationHMAC,
 )
-from allauth.tests import TestCase, patch
+from allauth.tests import Mock, TestCase, patch
 from allauth.utils import get_user_model, get_username_max_length
 
 from . import app_settings
 from ..compat import is_authenticated, reverse
 from .adapter import get_adapter
 from .auth_backends import AuthenticationBackend
+from .signals import user_logged_out
 from .utils import (
     filter_users_by_username,
     url_str_to_user_pk,
@@ -569,8 +570,21 @@ def test_logout_view_on_post(self):
         self.assertTemplateUsed(
             resp,
             'account/logout.%s' % app_settings.TEMPLATE_EXTENSION)
+
+        receiver_mock = Mock()
+        user_logged_out.connect(receiver_mock)
+
         resp = c.post(reverse('account_logout'))
+
         self.assertTemplateUsed(resp, 'account/messages/logged_out.txt')
+        receiver_mock.assert_called_once_with(
+            sender=get_user_model(),
+            request=resp.wsgi_request,
+            user=get_user_model().objects.get(username='john'),
+            signal=user_logged_out,
+        )
+
+        user_logged_out.disconnect(receiver_mock)
 
     def _logout_view(self, method):
         c = Client()