For a password change I am using auth_views.password_change
and for the password reset auth_views.password_reset
.
How can I be notified when a user successfully changes their password? I do not need to know old nor new password. Just that the event took place, and for which user.
Similarly, I would like to get notified when someone requested a password reset and also when they successfully completed the reset procedure.
Can i do the above with signals or some simple patching? Or do I need to write my own views to do this?
Create a decorator:
def notify_admins(func):
def wrapper(request, *args, **kwargs):
# send email to admins
return func(request, *args, **kwargs)
return wrapper
Then, just add wrap it around the appropriate views in your urls.py:
urlpatterns = patterns('',
...
(r'^password_change/done/$', notify_admins(auth_views.password_change_done)),
(r'^password_reset/done/$', notify_admins(auth_views.password_reset_done)),
(r'^reset/done/$', notify_admins(auth_views.password_reset_complete)),
...
)
Keep in mind that sending email directly from a view, or in this case a decorator, will tie up the request. Instead of sending the email there directly, it would be better to create a custom signal and a handler that will fire off a thread to actually send the email. Then, in the decorator, you simply send the signal.
You could write a custom password_change_form
that you pass to password_change
. This form would extend django's PasswordChangeForm
overriding its save method to first notify you of the change and then call it's parent PasswordChangeForm
s save method.
Docs on password_change view: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.password_change
Docs on ChangeForm: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.forms.PasswordChangeForm
Code for PasswordChangeForm: https://code.djangoproject.com/browser/django/trunk/django/contrib/auth/forms.py
Beginning in Django 1.9, you can define your define your own password validators. You could even simply re-define an existing one, if you like. When you do, add a method:
from django.contrib.auth.password_validation import MinimumLengthValidator
class MyPasswordValidator(MinimumLengthValidator):
def password_changed(self, password, user):
# put your password changed logic here
Be sure to include your new class in your settings as follows:
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'my_package.password_validators.MyPasswordValidator',
'OPTIONS': {
'min_length': 8,
}
},
...
]
Now, each time a password is changed by the user, your class MyPasswordValidator will be notified. In my experience, this is the best way to do this because:
I will caution you to be aware that the password parameter in password_changed() is in fact the user's raw password. Take care when handling this and absolutely never store this anywhere unencrypted/unhashed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With