2012-02-03 10 views
6

Do zmiany hasła używam auth_views.password_change i do resetowania hasła auth_views.password_reset.Jak otrzymać powiadomienie, gdy użytkownik zmieni hasło lub zażąda zresetowania hasła?

Jak mogę otrzymać powiadomienie, gdy użytkownik pomyślnie zmieni swoje hasło? Nie muszę znać starego ani nowego hasła. Tylko, że wydarzenie miało miejsce, i dla którego użytkownika.

Podobnie chciałbym otrzymać powiadomienie, gdy ktoś zażąda zresetowania hasła, a także po pomyślnym zakończeniu procedury resetowania.

Czy mogę to zrobić z sygnałami lub prostym łataniem? Czy muszę napisać własne poglądy, aby to zrobić?

Odpowiedz

7

Załóż dekorator:

def notify_admins(func): 
    def wrapper(request, *args, **kwargs): 
     # send email to admins 
     return func(request, *args, **kwargs) 
    return wrapper 

Potem tylko dodaj owinąć go wokół odpowiednich widoków w Twojej 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)), 
    ... 
) 

Pamiętaj, że wysyłanie wiadomości e-mail bezpośrednio z widokiem, lub w tym przypadku dekorator, będzie związać się wniosek. Zamiast bezpośredniego wysyłania wiadomości e-mail, lepiej jest utworzyć niestandardowy sygnał i program obsługi, który uruchomi wątek, aby wysłać wiadomość e-mail. Następnie w dekoratorze wystarczy wysłać sygnał.

+0

Arent sygnały synchroniczne mimo? Chyba, że ​​mail odbywa się w procesie asynchronicznym, czy to nie to samo? – jdi

+1

Stąd bit "odpalić nitkę". Jeśli utworzysz wątek, który wyśle ​​wiadomość e-mail w sygnale, wówczas stanie się on asynchroniczny. Sygnał zwraca przetwarzanie, a nowy wątek szczęśliwie przechodzi proces wysyłania wiadomości e-mail. –

+0

Ah tęsknię za tym trochę. Skoncentruję się na sygnałach – jdi

2

Jeśli już przy użyciu auth_views.password_change wybudowany w widoku, a następnie łatwo byłoby powiadomić siebie raz są przekierowywane po udanej zmiany:

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])

Jeśli funkcja post_change_redirect URL, aby przekierować do jednego z twoich własnych widoków, a następnie po prostu wykonaj dowolną akcję w tym widoku, aby wysłać powiadomienie (e-mail, aktualizacje bazy danych itp.).

można nawet w widoku przekierowania, tylko zrobić swoje zgłoszenie, a następnie powrót password_change_done(request[, template_name])

+1

to by działało. Jednak odświeżenie tego adresu URL również uruchomi akcję. Nawet ręczne wczytanie tego adresu URL uruchomiłoby go. Wolałbym unikać tych rzadkich, ale potencjalnych sposobów błędnego powiadomienia mnie o zmianie hasła. –

+0

Zgadzam się, że to spowodowałoby. Moja odpowiedź dotyczyła głównie części pytania o to, że nie trzeba naprawdę pisać własnego pełnego widoku. To po prostu pasuje do już istniejących. Jak zasugerowano w drugiej odpowiedzi, musiałbyś to zrobić poprzez rzeczywisty handler formularza. – jdi

4

można napisać niestandardowy password_change_form które przechodzą do password_change. Ten formularz rozszerzyłby django o PasswordChangeForm przesłanianie metody składowania, aby najpierw powiadomić o zmianie, a następnie nazwać ją metodą zapisu rodzica PasswordChangeForm.

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

Docs na ChangeForm: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.forms.PasswordChangeForm

kodują PasswordChangeForm: https://code.djangoproject.com/browser/django/trunk/django/contrib/auth/forms.py

1

Można również przechwycić sygnał i sprawdzić, czy hasło się zmieniło. Pamiętaj, że ten kod będzie działał za każdym razem, gdy zmieni się użytkownik.

@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 
+0

Pamiętaj też, że jeśli administrator zmieni parametry haszowania hasła, ten moduł obsługi sygnału zostanie wywołany dla każdego użytkownika przy następnym logowaniu. Jest to ważne, jeśli zamierzasz wymuszać zasady ważności hasła za pomocą tej procedury obsługi sygnału . – mkoistinen

2

Zaczynając od Django 1.9, możesz zdefiniować swój własny walidator haseł. Możesz nawet po prostu ponownie zdefiniować istniejący, jeśli chcesz.Gdy to zrobisz, dodać metodę:

from django.contrib.auth.password_validation import MinimumLengthValidator 
class MyPasswordValidator(MinimumLengthValidator): 

    def password_changed(self, password, user): 
     # put your password changed logic here 

Pamiętaj, aby podać swoją nową klasę w ustawieniach następująco:

AUTH_PASSWORD_VALIDATORS = [ 
    { 
     'NAME': 'my_package.password_validators.MyPasswordValidator', 
     'OPTIONS': { 
      'min_length': 8, 
     } 
    }, 
    ... 
] 

Teraz, za każdym razem hasło zostało zmienione przez użytkownika, klasa MyPasswordValidator zostanie powiadomiony. W moim doświadczeniu, jest to najlepszy sposób, aby to zrobić, ponieważ:

  1. Przy użyciu sygnałów, aby uchwycić te zdarzenia, będzie również przechwytywać zdarzenia, gdzie system ponownie kodowane istniejącego hasła z powodu zmian w mieszania parametrów, w większości przypadków nie chcesz przechwytywać tych zdarzeń i nie ma oczywistego sposobu, aby temu zapobiec za pomocą sygnałów.
  2. Możesz łatwo dodać wywołanie funkcji w metodzie save() wszystkich formularzy obsługi haseł, ale to staje się trudne, gdy chcesz zrobić to samo z wbudowanym formularzem zmiany hasła administratora i nie pomoże, jeśli zmiany hasła dokonywane są programowo poza formularzem.

Będę ostrzegać, aby mieć świadomość, że parametr password w password_changed() jest w rzeczywistości nieprzetworzonym hasłem użytkownika. Zachowaj ostrożność podczas obchodzenia się z tym i absolutnie nigdy nie przechowuj tego w żadnym miejscu niezaszyfrowanym/nierozpakowanym.

Powiązane problemy