forgottenpassword.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from faker import Factory
  2. from django.contrib import messages
  3. from django.contrib.auth import get_user_model
  4. from django.http import Http404
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.utils.translation import ugettext as _
  7. from misago.conf import settings
  8. from misago.core.mail import mail_user
  9. from misago.users.bans import get_user_ban
  10. from misago.users.decorators import deny_authenticated, deny_banned_ips
  11. from misago.users.forms.auth import ResetPasswordForm
  12. from misago.users.models import ACTIVATION_REQUIRED_NONE
  13. from misago.users.tokens import (make_password_reset_token,
  14. is_password_reset_token_valid)
  15. def reset_view(f):
  16. @deny_authenticated
  17. @deny_banned_ips
  18. def decorator(*args, **kwargs):
  19. return f(*args, **kwargs)
  20. return decorator
  21. @reset_view
  22. def request_reset(request):
  23. form = ResetPasswordForm()
  24. if request.method == 'POST':
  25. form = ResetPasswordForm(request.POST)
  26. if form.is_valid():
  27. requesting_user = form.user_cache
  28. request.session['confirmation_sent_to'] = requesting_user.pk
  29. mail_subject = _("Confirm %(username)s password change "
  30. "on %(forum_title)s forums")
  31. subject_formats = {'username': requesting_user.username,
  32. 'forum_title': settings.forum_name}
  33. mail_subject = mail_subject % subject_formats
  34. confirmation_token = make_password_reset_token(requesting_user)
  35. mail_user(
  36. request, requesting_user, mail_subject,
  37. 'misago/emails/forgottenpassword/confirm',
  38. {'confirmation_token': confirmation_token})
  39. return redirect('misago:reset_password_confirmation_sent')
  40. return render(request, 'misago/forgottenpassword/request.html',
  41. {'form': form})
  42. @reset_view
  43. def confirmation_sent(request):
  44. requesting_user_pk = request.session.get('confirmation_sent_to')
  45. if not requesting_user_pk:
  46. raise Http404()
  47. User = get_user_model()
  48. requesting_user = get_object_or_404(User.objects, pk=requesting_user_pk)
  49. return render(request, 'misago/forgottenpassword/confirmation_sent.html',
  50. {'requesting_user': requesting_user})
  51. class ResetStopped(Exception):
  52. pass
  53. class ResetError(Exception):
  54. pass
  55. @reset_view
  56. def reset_password(request, user_id, token):
  57. User = get_user_model()
  58. requesting_user = get_object_or_404(User.objects, pk=user_id)
  59. try:
  60. if requesting_user.requires_activation_by_admin:
  61. message = _("%(username)s, administrator has to activate your "
  62. "account before you will be able to request "
  63. "new password.")
  64. message = message % {'username': requesting_user.username}
  65. raise ResetStopped(message)
  66. if requesting_user.requires_activation_by_user:
  67. message = _("%(username)s, you have to activate your account "
  68. "before you will be able to request new password.")
  69. message = message % {'username': requesting_user.username}
  70. raise ResetStopped(message)
  71. if get_user_ban(requesting_user):
  72. message = _("%(username)s, your account is banned "
  73. "and it's password can't be changed.")
  74. message = message % {'username': requesting_user.username}
  75. raise ResetError(message)
  76. if not is_password_reset_token_valid(requesting_user, token):
  77. message = _("%(username)s, your confirmation link is invalid. "
  78. "Try again or request new confirmation message.")
  79. message = message % {'username': requesting_user.username}
  80. raise ResetError(message)
  81. except ResetStopped as e:
  82. messages.info(request, e.args[0])
  83. return redirect('misago:index')
  84. except ResetError as e:
  85. messages.error(request, e.args[0])
  86. return redirect('misago:request_password_reset')
  87. fake = Factory.create()
  88. new_password = ' '.join([fake.word() for x in xrange(4)])
  89. while len(new_password) < settings.password_length_min:
  90. new_password = '%s %s' % (new_password, fake.word())
  91. requesting_user.set_password(new_password)
  92. requesting_user.save(update_fields=['password'])
  93. mail_subject = _("New password on %(forum_title)s forums")
  94. mail_subject = mail_subject % {'forum_title': settings.forum_name}
  95. confirmation_token = make_password_reset_token(requesting_user)
  96. mail_user(
  97. request, requesting_user, mail_subject,
  98. 'misago/emails/forgottenpassword/new',
  99. {'new_password': new_password})
  100. request.session['password_sent_to'] = requesting_user.pk
  101. return redirect('misago:request_password_new_sent')
  102. @reset_view
  103. def new_password_sent(request):
  104. requesting_user_pk = request.session.get('password_sent_to')
  105. if not requesting_user_pk:
  106. raise Http404()
  107. User = get_user_model()
  108. requesting_user = get_object_or_404(User.objects, pk=requesting_user_pk)
  109. return render(request, 'misago/forgottenpassword/password_sent.html',
  110. {'requesting_user': requesting_user})