How to receive notifications when a user changes a password or asks for a reset password?

To change the password, I use auth_views.password_change and for the password reset auth_views.password_reset .

How can I get a notification when a user successfully changes his password? I do not need to know the old or new password. Just this event took place and for which user.

Similarly, I would like to receive a notification when someone asked for the reset password, and also when they successfully completed the reset procedure.

Can I do this with signals or some simple fixes? Or do I need to write my own views to do this?

+6
source share
5 answers

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 a wrapper around the corresponding views in 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 the view or in this case the decorator will link the request. Instead of sending the email directly, it would be better to create your own signal and a handler that will disconnect the stream to actually send the email. Then, in the decorator, you simply send a signal.

+7
source

You can write a custom password_change_form that you pass to password_change . This form extends django PasswordChangeForm by overriding its save method to notify you of this change first and then call its parent method PasswordChangeForm save.

Documents in password view: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.password_change

ChangeForm docs: 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

+4
source

If you already use the built-in view auth_views.password_change , then it would be easy to notify yourself as soon as they are redirected after a successful change:

https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.password_change

password_change(request[, template_name, post_change_redirect, password_change_form])

If you set the post_change_redirect URL to redirect to one of your own views, you simply do whatever you want in that view to send a notification (email, database updates, etc.).

You can even make your notification in your forwarding, and then return password_change_done(request[, template_name])

+2
source

Starting with Django 1.9, you can determine how to define your own password checks. If you want, you can even just override the existing one. 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, every time the password is changed by the user, your MyPasswordValidator class will be notified. In my experience, this is the best way to do this because:

  • When using signals to capture these events, you will also record events in which the system has re-encoded an existing password due to a change in the hashing parameters, in most cases you would not want to capture these events, and there is no obvious way to prevent it with signals.
  • You can simply add a call function to the save () method of all forms of password processing, but this becomes difficult if you want to do the same with the built-in administrator password form, but you cannot, if password changes are made programmatically outside the form.

I warn you that you know that the password parameter in password_changed () is the user's raw password. Exercise caution when handling this and absolutely never store it anywhere unencrypted / unhashed.

+2
source

You can also capture the signal and check if the password has changed. Just keep in mind that this code will run every time the user changes.

 @receiver(pre_save, sender=User) def record_password_change(sender, **kwargs): user = kwargs.get('instance', None) if user: new_password = user.password try: old_password = User.objects.get(pk=user.pk).password except User.DoesNotExist: old_password = None if new_password != old_password: # do what you need here 
+1
source

Source: https://habr.com/ru/post/907597/


All Articles