Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Ticket #18616: contrib.auth signal user_login_fail #201

Closed
wants to merge 12 commits into from

4 participants

Michael Farrell Florian Apolloner Brad Pitcher Jannis Leidel
Michael Farrell

https://code.djangoproject.com/ticket/18616

Note: it seems I made a typo on the branch name, it is ticket_18686 instead of ticket_18616.

Brad Pitcher

I personally think user_login_failed would be a better name for this signal, to better match the verb form of the other two.

You raise a good point Brad, I'll update this pull request with another commit changing to this.

Michael Farrell per a suggestion by Brad Pitcher, I have changed the signal name to "…
…user_login_failed" to match the verb tense of the other signals emitted by contrib.auth.
3918f25
Florian Apolloner
Owner

@brad, @micolous Please incorporate the Doc PR into this PR.

Brad Pitcher
brad commented July 17, 2012

I'll send a pull request your way, @micolous

Brad Pitcher
brad commented July 17, 2012

GitHub won't let me send you a pull request, even when I branch directly from you. If you like you could pull my ticket_18616_docs branch to get the docs. I made updated to the sender documentation.

Michael Farrell

Done.

Brad Pitcher
brad commented July 18, 2012

Sorry, looks like I forgot to get that sender doc change in that branch. I have made the change now if you want to pull again.

Jannis Leidel
Owner
jezdez commented July 21, 2012

Remember folks to always mention in the ticket which pull request is the correct one!

Brad Pitcher
brad commented July 21, 2012

Sorry, my mistake.

Michael Farrell

Merged Brad's documentation fixes.

Brad Pitcher

This patch no longer applies cleanly to master. Can you fix it, or pull from https://github.com/brad/django/tree/ticket_18616. We are in the middle of a sprint so we may manage to get it merged in today.

Florian Apolloner
Owner

This was fixed in 7cc4068

Florian Apolloner apollo13 closed this January 01, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
5  django/contrib/auth/__init__.py
... ...
@@ -1,6 +1,6 @@
1 1
 from django.core.exceptions import ImproperlyConfigured
2 2
 from django.utils.importlib import import_module
3  
-from django.contrib.auth.signals import user_logged_in, user_logged_out
  3
+from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
4 4
 
5 5
 SESSION_KEY = '_auth_user_id'
6 6
 BACKEND_SESSION_KEY = '_auth_user_backend'
@@ -45,6 +45,9 @@ def authenticate(**credentials):
45 45
         # Annotate the user object with the path of the backend.
46 46
         user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
47 47
         return user
  48
+        
  49
+    # The credentials supplied are invalid to all backends, fire signal
  50
+    user_login_failed.send(sender=__name__, credentials=credentials)
48 51
 
49 52
 def login(request, user):
50 53
     """
1  django/contrib/auth/signals.py
... ...
@@ -1,4 +1,5 @@
1 1
 from django.dispatch import Signal
2 2
 
3 3
 user_logged_in = Signal(providing_args=['request', 'user'])
  4
+user_login_failed = Signal(providing_args=['credentials'])
4 5
 user_logged_out = Signal(providing_args=['request', 'user'])
14  django/contrib/auth/tests/signals.py
@@ -16,27 +16,39 @@ def listener_login(self, user, **kwargs):
16 16
     def listener_logout(self, user, **kwargs):
17 17
         self.logged_out.append(user)
18 18
 
  19
+    def listener_login_failed(self, sender, credentials, **kwargs):
  20
+        self.login_failed.append(credentials['username'])
  21
+
19 22
     def setUp(self):
20 23
         """Set up the listeners and reset the logged in/logged out counters"""
21 24
         self.logged_in = []
22 25
         self.logged_out = []
  26
+        self.login_failed = []
23 27
         signals.user_logged_in.connect(self.listener_login)
24 28
         signals.user_logged_out.connect(self.listener_logout)
  29
+        signals.user_login_failed.connect(self.listener_login_failed)
25 30
 
26 31
     def tearDown(self):
27 32
         """Disconnect the listeners"""
28 33
         signals.user_logged_in.disconnect(self.listener_login)
29 34
         signals.user_logged_out.disconnect(self.listener_logout)
  35
+        signals.user_login_failed.disconnect(self.listener_login_failed)
30 36
 
31 37
     def test_login(self):
32  
-        # Only a successful login will trigger the signal.
  38
+        # Only a successful login will trigger the success signal.
33 39
         self.client.login(username='testclient', password='bad')
34 40
         self.assertEqual(len(self.logged_in), 0)
  41
+        self.assertEqual(len(self.login_failed), 1)
  42
+        self.assertEqual(self.login_failed[0], 'testclient')
  43
+
35 44
         # Like this:
36 45
         self.client.login(username='testclient', password='password')
37 46
         self.assertEqual(len(self.logged_in), 1)
38 47
         self.assertEqual(self.logged_in[0].username, 'testclient')
39 48
 
  49
+        # Ensure there were no more failures.
  50
+        self.assertEqual(len(self.login_failed), 1)
  51
+
40 52
     def test_logout_anonymous(self):
41 53
         # The log_out function will still trigger the signal for anonymous
42 54
         # users.
4  docs/releases/1.5.txt
@@ -121,6 +121,10 @@ Django 1.5 also includes several smaller improvements worth noting:
121 121
   argument. By default the batch_size is unlimited except for SQLite where
122 122
   single batch is limited so that 999 parameters per query isn't exceeded.
123 123
 
  124
+* :mod:`django.contrib.auth` provides a new signal that is emitted
  125
+  whenever a user fails to login successfully. See
  126
+  :data:`~django.contrib.auth.signals.user_login_failed`
  127
+
124 128
 * The :setting:`LOGIN_URL` and :setting:`LOGIN_REDIRECT_URL` settings now also
125 129
   accept view function names and
126 130
   :ref:`named URL patterns <naming-url-patterns>`. This allows you to reduce
21  docs/topics/auth.txt
@@ -866,13 +866,15 @@ The auth framework uses two :doc:`signals </topics/signals>` that can be used
866 866
 for notification when a user logs in or out.
867 867
 
868 868
 .. data:: django.contrib.auth.signals.user_logged_in
  869
+   :module:
  870
+.. versionadded:: 1.3
869 871
 
870 872
 Sent when a user logs in successfully.
871 873
 
872 874
 Arguments sent with this signal:
873 875
 
874 876
 ``sender``
875  
-    As above: the class of the user that just logged in.
  877
+    The class of the user that just logged in.
876 878
 
877 879
 ``request``
878 880
     The current :class:`~django.http.HttpRequest` instance.
@@ -881,6 +883,8 @@ Arguments sent with this signal:
881 883
     The user instance that just logged in.
882 884
 
883 885
 .. data:: django.contrib.auth.signals.user_logged_out
  886
+   :module:
  887
+.. versionadded:: 1.3
884 888
 
885 889
 Sent when the logout method is called.
886 890
 
@@ -895,6 +899,21 @@ Sent when the logout method is called.
895 899
     The user instance that just logged out or ``None`` if the
896 900
     user was not authenticated.
897 901
 
  902
+.. data:: django.contrib.auth.signals.user_login_failed
  903
+   :module:
  904
+.. versionadded:: 1.5
  905
+
  906
+Sent when the user failed to login successfully
  907
+
  908
+``sender``
  909
+    The name of the module used for authentication.
  910
+
  911
+``credentials``
  912
+    A dictonary of keyword arguments containing the user credentials that
  913
+    were passed to :func:`~django.contrib.auth.authenticate()` or
  914
+    your own custom authentication backend. Most of the time this dictionary
  915
+    will just include ``username`` and ``password``.
  916
+
898 917
 Limiting access to logged-in users
899 918
 ----------------------------------
900 919
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.