import web from uuid import uuid4 from views.forms import reset_form, request_reset_form from views.utils import get_nav_bar, csrf_protected, get_render, password_weakness, sendmail import models.user import logging import bcrypt logger = logging.getLogger(__name__) class RequestReset: def GET(self): session = web.ctx.session nav = get_nav_bar(session) return get_render().reset_request(nav, request_reset_form, "") @csrf_protected def POST(self): session = web.ctx.session nav = get_nav_bar(session) data = web.input(username="", email="") render = get_render() user = models.user.get_user(data.username) if user and user[2] == data.email: password = uuid4().hex password_hash = bcrypt.hashpw(password.encode('UTF-8'), bcrypt.gensalt()) models.user.set_temporary_password(user[0], password_hash) sendmail( 'Reset your Beelance password', """Hi! Someone requested a password reset for your account. If you didn't request this, you can ignore this email. If you want to reset your password, log in with this password: {password} Then you will be able to set a new password. """.format(password=password), "", data.email, ) logger.info("User %s requested a password reset", data.username) else: logger.info("Incorrect reset request with username %s and email %s", data.username, data.email) return render.reset_request(nav, request_reset_form, "An email has been sent, if the username and email is correct") class Reset: def GET(self): session = web.ctx.session nav = get_nav_bar(session) render = get_render() if 'temporary_userid' not in session or not session.temporary_userid: return render.reset(nav, reset_form, "Something went wrong. Try logging in with the temporary password again.") return get_render().reset(nav, reset_form, "") @csrf_protected def POST(self): session = web.ctx.session nav = get_nav_bar(session) data = web.input(temporary="", password="", repeat="") render = get_render() if 'temporary_userid' not in session or not session.temporary_userid: return render.reset(nav, reset_form, "Something went wrong. Try logging in with the temporary password again.") userid = session.temporary_userid username = models.user.get_user_name_by_id(userid) user = models.user.get_user(username) temporary_password = user[4] # Check that the temporary password is correct if not bcrypt.checkpw(data.temporary.encode('UTF-8'), temporary_password.encode('UTF-8')): return render.reset(nav, reset_form, "Incorrect temporary password") # Check that the passwords match if data.password != data.repeat: return render.reset(nav, reset_form, "The repeated password doesn't match the first") # Check password security weakness = password_weakness(data.password, username) if weakness is not None: return render.reset(nav, reset_form, weakness) # Set the new password and log the user in password_hash = bcrypt.hashpw(data.password.encode('UTF-8'), bcrypt.gensalt()) models.user.set_password(userid, password_hash) models.user.set_temporary_password(userid, "") session.temporary_userid = None logger.info("User %s has changed their password", username) return get_render().reset(nav, reset_form, "Your password has been reset. You can log in again now.")