Skip to content
Snippets Groups Projects
Unverified Commit bb42675c authored by Sandro Lutz's avatar Sandro Lutz
Browse files

Add password reset

parent fefe7661
No related branches found
No related tags found
No related merge requests found
......@@ -11,7 +11,6 @@ def login_required(f):
"""
@wraps(f)
def wrapped(*args, **kwargs):
print('test')
if not is_authenticated():
abort(403)
......@@ -33,7 +32,7 @@ def login(email, password):
user = User.query.filter(User.email == email).first()
if user.check_password(password):
if user and user.check_password(password):
session['userID'] = user._id
return True
return False
......
......@@ -3,7 +3,7 @@ from datetime import datetime
from sqlalchemy import DateTime, cast, func
from validate_email import validate_email
from flask_mail import Message
from flask import current_app, render_template
from flask import current_app, render_template, url_for
from app import db, mail
from app.models import User
from .lock import Lock
......@@ -71,14 +71,19 @@ class UserController():
@staticmethod
def verify_confirm_email(email, token):
user = User.query.filter(User.email == email).first()
def get_by_email(email):
return User.query.filter(User.email == email).first()
@classmethod
def verify_confirm_email(cls, email, token):
user = cls.get_by_email(email)
return user is not None and user.is_token_valid(token)
@staticmethod
def confirm_email(email, token):
user = User.query.filter(User.email == email).first()
@classmethod
def confirm_email(cls, email, token):
user = cls.get_by_email(email)
if user is None or not user.is_token_valid(token):
return False
......@@ -89,6 +94,19 @@ class UserController():
return True
@classmethod
def reset_password(cls, email, token, password):
user = cls.get_by_email(email)
if user is None or not user.is_token_valid(token):
return False
user.set_password(password)
user.generate_new_token()
db.session.commit()
return True
@staticmethod
def reserve(user):
if ReservationController.has_active_reservation(user):
......@@ -124,9 +142,11 @@ class UserController():
@staticmethod
def send_password_reset_email(user):
user.generate_new_token()
sesssion.commit()
msg = Message(render_template('email/password_reset.txt', user=user),
db.session.commit()
msg = Message(subject='[Bastli Bouncer] Reset Password',
body=render_template('email/password_reset.txt', user=user),
recipients=[user.email])
print(url_for('login.password_reset', token=user.token, email=user.email, _external=True))
mail.send(msg)
......@@ -136,5 +156,5 @@ class UserController():
subject='[Bastli Bouncer] Confirm Email Address',
body=render_template('email/confirm.txt', user=user),
recipients=[user.email])
print(msg)
print(url_for('login.confirm_email', token=user.token, email=user.email, _external=True))
mail.send(msg)
......@@ -58,8 +58,41 @@ def login():
return make_response(render_template('login/login.html', title='Login'))
@login_bp.route('/password_reset', methods=['GET', 'POST'])
def password_reset(token, email):
@login_bp.route('/password/forgotten', methods=['GET', 'POST'])
def password_forgotten():
if is_authenticated():
return redirect(url_for('bouncer.home'))
errors = None
if request.method == 'POST':
user = UserController.get_by_email(request.form['email'])
if user:
UserController.send_password_reset_email(user)
flash('Instructions on how to reset the password has been sent the your email inbox.')
return redirect(url_for('login.login'))
return make_response(render_template('login/password_forgotten.html', title='Forgotten Password'))
@login_bp.route('/password/reset', methods=['GET', 'POST'])
def password_reset():
email = request.args.get('email')
token = request.args.get('token')
if not UserController.verify_confirm_email(email, token):
abort(404)
if request.method == 'POST':
if request.form['password'] is not None and \
len(request.form['password']) > 0 and \
request.form['password'] == request.form['password2']:
if UserController.reset_password(email, token, request.form['password']):
flash('Password has been reset! Please try to log in with the new password.')
return redirect(url_for('login.login'))
else:
flash('Could not reset password. An unknown error has occured.', 'error')
else:
flash('Passwords do not match.', 'error')
return make_response(render_template('login/password_reset.html', title='Password Reset'))
......
Hi {{ user.name }}
You requested to reset the password for your account.
If that was not you, this message can be ignored.
Please follow the instructions at the link below.
......
......@@ -17,6 +17,7 @@
<input type="password" id="password" name="password" value="{{ request.form.password }}"><br/>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<input class="btn btn-primary" type="submit" value="Login"> or
<a class="btn btn-default" role="button" href="{{ url_for('login.password_forgotten') }}">Password forgotten?</a> or
<a class="btn btn-default" role="button" href="{{ url_for('bouncer.home') }}">Go back</a>
</form>
</div>
......
{% import "bootstrap/utils.html" as utils %}
{% extends "base.html" %}
{% block body %}
<div class="content-section">
<br/>
{{ utils.flashed_messages() }}
<br/>
<div class="center-narrow">
<h1>Bastli Bouncer</h1>
<br/>
<h2>Password forgotten?</h2>
<br>
<p>Request instructions for resetting the password.</p>
<form action="" method="post">
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" value="{{ request.form.email }}"><br/>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<input class="btn btn-primary" type="submit" value="Request password reset"> or
<a class="btn btn-default" role="button" href="{{ url_for('login.login') }}">Go back</a>
</form>
</div>
</div>
{% endblock %}
{% import "bootstrap/utils.html" as utils %}
{% extends "base.html" %}
{% block body %}
<div class="content-section">
<br/>
{{ utils.flashed_messages() }}
<br/>
<div class="center-narrow">
<h1>Bastli Bouncer</h1>
<br/>
<h2>Set a new Password</h2>
<br>
<p>Set a new password for {{ email }}.</p>
<form action="" method="post">
<label for="name">New Password:</label><br>
<input type="password" id="password" name="password" value="{{ request.form.password }}"><br/>
<label for="name">Repeat new Password:</label><br>
<input type="password" id="password2" name="password2" value="{{ request.form.password2 }}"><br/>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<input class="btn btn-primary" type="submit" value="Set new Password"> or
<a class="btn btn-default" role="button" href="{{ url_for('login.login') }}">Go back</a>
</form>
</div>
</div>
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment