From 8e753be8e89aa3b366613e46811e5b1692217652 Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 10:52:46 +0200 Subject: [PATCH 1/6] Add Flask-Mail for e-mail support. --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 5e13218c..a4367aa7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ Flask==1.0.3 Flask-Login==0.4.1 +Flask-Mail==0.9.1 Flask-Migrate==2.5.2 Flask-SQLAlchemy==2.4.0 Flask-WTF==0.14.2 From d6ec00d9cf8706cf57e8ef35b128709eae16fe0f Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 10:53:14 +0200 Subject: [PATCH 2/6] Add e-mail related configurations. --- .flaskenv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.flaskenv b/.flaskenv index f88b6e5b..0a7611db 100644 --- a/.flaskenv +++ b/.flaskenv @@ -1,2 +1,4 @@ FLASK_APP=opaque.py FLASK_ENV=development +OPAQUE_MAIL_SUBJECT_PREFIX=[Opaque] +OPAQUE_MAIL_SENDER=Opaque Admin From 3e8ce1e719de1f788fb3d2b1aac63a42db4fc12a Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 10:53:54 +0200 Subject: [PATCH 3/6] Add Flask-Mail to app instance. --- app/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/__init__.py b/app/__init__.py index f77d7e22..7080fdbc 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,10 +1,12 @@ from config import config from flask import Flask from flask_login import LoginManager +from flask_mail import Mail from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() +mail = Mail() login_manager = LoginManager() login_manager.login_view = 'auth.login' @@ -17,6 +19,7 @@ def create_app(config_name): db.init_app(app) login_manager.init_app(app) + mail.init_app(app) from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') From 311498415bc270db3a2ef00357e48770e4a5fcd1 Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 10:54:29 +0200 Subject: [PATCH 4/6] Add form for password reset request. --- app/auth/forms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/auth/forms.py b/app/auth/forms.py index d50cf956..cf7cc7d5 100644 --- a/app/auth/forms.py +++ b/app/auth/forms.py @@ -9,3 +9,9 @@ class LoginForm(FlaskForm): password = PasswordField('Password', validators=[DataRequired()]) remember_me = BooleanField('Keep me logged in') submit = SubmitField('Log In') + + +class PasswordResetRequestForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Length(1, 64), + Email()]) + submit = SubmitField('Reset Password') From 4076e44194093a2822c93c7206168a35e6e0385a Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 11:00:49 +0200 Subject: [PATCH 5/6] Add e-mail templates for password reset request. --- app/templates/auth/email/reset_password.html | 8 ++++++++ app/templates/auth/email/reset_password.txt | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 app/templates/auth/email/reset_password.html create mode 100644 app/templates/auth/email/reset_password.txt diff --git a/app/templates/auth/email/reset_password.html b/app/templates/auth/email/reset_password.html new file mode 100644 index 00000000..5b58a220 --- /dev/null +++ b/app/templates/auth/email/reset_password.html @@ -0,0 +1,8 @@ +

Dear {{ user.username }},

+

To reset your password click here.

+

Alternatively, you can paste the following link in your browser's address bar:

+

{{ url_for('auth.password_reset', token=token, _external=True) }}

+

If you have not requested a password reset simply ignore this message.

+

Sincerely,

+

The Opaque Team

+

Note: replies to this email address are not monitored.

diff --git a/app/templates/auth/email/reset_password.txt b/app/templates/auth/email/reset_password.txt new file mode 100644 index 00000000..cecc5a24 --- /dev/null +++ b/app/templates/auth/email/reset_password.txt @@ -0,0 +1,13 @@ +Dear {{ user.username }}, + +To reset your password click on the following link: + +{{ url_for('auth.password_reset', token=token, _external=True) }} + +If you have not requested a password reset simply ignore this message. + +Sincerely, + +The Opaque Team + +Note: replies to this email address are not monitored. From dd4fcdfe208c22db290cfabd29bf8c42698c11e4 Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Mon, 8 Jul 2019 11:04:52 +0200 Subject: [PATCH 6/6] Add password reset request view. --- app/auth/views.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/auth/views.py b/app/auth/views.py index 5eef5868..b2e6ba68 100644 --- a/app/auth/views.py +++ b/app/auth/views.py @@ -1,7 +1,8 @@ from flask import flash, redirect, render_template, request, url_for from flask_login import login_required, login_user, logout_user from . import auth -from .forms import LoginForm +from .forms import LoginForm, PasswordResetRequestForm +from ..email import send_email from ..models import User @@ -31,3 +32,18 @@ def logout(): @auth.route('/register', methods=['GET', 'POST']) def register(): return render_template('auth/register.html.j2') + + +@auth.route('/reset', methods=['GET', 'POST']) +def password_reset_request(): + form = PasswordResetRequestForm() + if form.validate_on_submit(): + user = User.query.filter_by(email=form.email.data.lower()).first() + if user: + token = user.generate_reset_token() + send_email(user.email, 'Reset Your Password', + 'auth/email/reset_password', + user=user, token=token) + flash('An email with instructions to reset your password has been ' + 'sent to you.') + return redirect(url_for('auth.login'))