Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

100 lines
3.6KB

  1. import web
  2. from uuid import uuid4
  3. from views.forms import reset_form, request_reset_form
  4. from views.utils import get_nav_bar, csrf_protected, get_render, password_weakness, sendmail
  5. import models.user
  6. import logging
  7. import bcrypt
  8. logger = logging.getLogger(__name__)
  9. class RequestReset:
  10. def GET(self):
  11. session = web.ctx.session
  12. nav = get_nav_bar(session)
  13. return get_render().reset_request(nav, request_reset_form, "")
  14. @csrf_protected
  15. def POST(self):
  16. session = web.ctx.session
  17. nav = get_nav_bar(session)
  18. data = web.input(username="", email="")
  19. render = get_render()
  20. user = models.user.get_user(data.username)
  21. if user and user[2] == data.email:
  22. password = uuid4().hex
  23. password_hash = bcrypt.hashpw(password.encode('UTF-8'), bcrypt.gensalt())
  24. models.user.set_temporary_password(user[0], password_hash)
  25. sendmail(
  26. 'Reset your Beelance password',
  27. """Hi!
  28. Someone requested a password reset for your account. If you didn't request this, you can ignore this email.
  29. If you want to reset your password, log in with this password: {password}
  30. Then you will be able to set a new password.
  31. """.format(password=password),
  32. "",
  33. data.email,
  34. )
  35. logger.info("User %s requested a password reset", data.username)
  36. else:
  37. logger.info("Incorrect reset request with username %s and email %s", data.username, data.email)
  38. return render.reset_request(nav, request_reset_form, "An email has been sent, if the username and email is correct")
  39. class Reset:
  40. def GET(self):
  41. session = web.ctx.session
  42. nav = get_nav_bar(session)
  43. render = get_render()
  44. if 'temporary_userid' not in session or not session.temporary_userid:
  45. return render.reset(nav, reset_form, "Something went wrong. Try logging in with the temporary password again.")
  46. return get_render().reset(nav, reset_form, "")
  47. @csrf_protected
  48. def POST(self):
  49. session = web.ctx.session
  50. nav = get_nav_bar(session)
  51. data = web.input(temporary="", password="", repeat="")
  52. render = get_render()
  53. if 'temporary_userid' not in session or not session.temporary_userid:
  54. return render.reset(nav, reset_form, "Something went wrong. Try logging in with the temporary password again.")
  55. userid = session.temporary_userid
  56. username = models.user.get_user_name_by_id(userid)
  57. user = models.user.get_user(username)
  58. temporary_password = user[4]
  59. # Check that the temporary password is correct
  60. if not bcrypt.checkpw(data.temporary.encode('UTF-8'), temporary_password.encode('UTF-8')):
  61. return render.reset(nav, reset_form, "Incorrect temporary password")
  62. # Check that the passwords match
  63. if data.password != data.repeat:
  64. return render.reset(nav, reset_form, "The repeated password doesn't match the first")
  65. # Check password security
  66. weakness = password_weakness(data.password, username)
  67. if weakness is not None:
  68. return render.reset(nav, reset_form, weakness)
  69. # Set the new password and log the user in
  70. password_hash = bcrypt.hashpw(data.password.encode('UTF-8'), bcrypt.gensalt())
  71. models.user.set_password(userid, password_hash)
  72. models.user.set_temporary_password(userid, "")
  73. session.temporary_userid = None
  74. logger.info("User %s has changed their password", username)
  75. return get_render().reset(nav, reset_form, "Your password has been reset. You can log in again now.")