add password reset
This commit is contained in:
parent
edbe2e2395
commit
ff4617196f
|
@ -17,7 +17,7 @@ class SignupForm(Form):
|
||||||
[InputRequired(), Email(),
|
[InputRequired(), Email(),
|
||||||
Length(min=5, max=EMAIL_LEN)],
|
Length(min=5, max=EMAIL_LEN)],
|
||||||
description="we never share your e-mail address")
|
description="we never share your e-mail address")
|
||||||
password = PasswordField('password',
|
password = StringField('password',
|
||||||
[InputRequired(), Length(min=4, max=PASSWORD_LEN)])
|
[InputRequired(), Length(min=4, max=PASSWORD_LEN)])
|
||||||
|
|
||||||
def validate_username(form, field):
|
def validate_username(form, field):
|
||||||
|
@ -51,8 +51,12 @@ class LoginForm(Form):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class ForgotPasswordForm(Form):
|
class ForgotPasswordForm(Form):
|
||||||
username_or_email = StringField('username or e-mail address',
|
user_or_email = StringField('username or e-mail address',
|
||||||
[InputRequired(), Length(max=EMAIL_LEN)])
|
[InputRequired(), Length(max=EMAIL_LEN)])
|
||||||
|
|
||||||
|
class PasswordForm(Form):
|
||||||
|
password = PasswordField('new password',
|
||||||
|
[InputRequired(), Length(min=4, max=PASSWORD_LEN)])
|
||||||
|
|
||||||
class AccountSettingsForm(Form):
|
class AccountSettingsForm(Form):
|
||||||
full_name = StringField('full name', [Length(max=64)])
|
full_name = StringField('full name', [Length(max=64)])
|
||||||
|
|
10
sourcing/templates/auth/password_reset.html
Normal file
10
sourcing/templates/auth/password_reset.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% from "form/controls.html" import render_field, checkbox, submit %}
|
||||||
|
|
||||||
|
{% set title="Reset password" %}
|
||||||
|
{% set label="send e-mail" %}
|
||||||
|
|
||||||
|
{% set fields %}
|
||||||
|
{{ render_field(form.user_or_email) }}
|
||||||
|
{% endset %}
|
||||||
|
|
||||||
|
{% include "form/simple.html" %}
|
19
sourcing/templates/auth/password_reset_complete.html
Normal file
19
sourcing/templates/auth/password_reset_complete.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% from "form/controls.html" import render_field, checkbox, submit %}
|
||||||
|
|
||||||
|
{% set title="Reset password" %}
|
||||||
|
{% set label="send e-mail" %}
|
||||||
|
|
||||||
|
{% include "head.html" %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
|
<p>Your password has been set. You may go ahead and log in now.</p>
|
||||||
|
|
||||||
|
<p><a href="{{ url_for('.login') }}">Log in</a></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "foot.html" %}
|
10
sourcing/templates/auth/password_reset_confirm.html
Normal file
10
sourcing/templates/auth/password_reset_confirm.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% from "form/controls.html" import render_field %}
|
||||||
|
|
||||||
|
{% set title="Reset password" %}
|
||||||
|
{% set label="reset" %}
|
||||||
|
|
||||||
|
{% set fields %}
|
||||||
|
{{ render_field(form.password) }}
|
||||||
|
{% endset %}
|
||||||
|
|
||||||
|
{% include "form/simple.html" %}
|
17
sourcing/templates/auth/password_reset_sent.html
Normal file
17
sourcing/templates/auth/password_reset_sent.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% from "form/controls.html" import render_field, checkbox, submit %}
|
||||||
|
|
||||||
|
{% set title="Reset password" %}
|
||||||
|
{% set label="send e-mail" %}
|
||||||
|
|
||||||
|
{% include "head.html" %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<p>We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.</p>
|
||||||
|
|
||||||
|
<p>If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "foot.html" %}
|
|
@ -7,7 +7,17 @@
|
||||||
{% set fields %}
|
{% set fields %}
|
||||||
{{ render_field(form.user_or_email) }}
|
{{ render_field(form.user_or_email) }}
|
||||||
{{ render_field(form.password) }}
|
{{ render_field(form.password) }}
|
||||||
{{ checkbox(form.remember) }}
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="checkbox-inline">
|
||||||
|
{{ form.remember() }}
|
||||||
|
{{ form.remember.label.text }}
|
||||||
|
</label>
|
||||||
|
·
|
||||||
|
<a href="{{ url_for('.password_reset') }}">forgot password?</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endset %}
|
{% endset %}
|
||||||
|
|
||||||
{% include "form/simple.html" %}
|
{% include "form/simple.html" %}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from flask import (Blueprint, render_template, request, redirect, flash,
|
from flask import (Blueprint, render_template, request, redirect, flash,
|
||||||
url_for, abort, jsonify, Response)
|
url_for, abort, jsonify, Response, current_app)
|
||||||
from flask_login import (login_user, current_user, logout_user,
|
from flask_login import (login_user, current_user, logout_user,
|
||||||
login_required, LoginManager)
|
login_required, LoginManager)
|
||||||
from .forms import (LoginForm, SignupForm, AccountSettingsForm,
|
from .forms import (LoginForm, SignupForm, AccountSettingsForm,
|
||||||
UploadSourceDocForm, SourceDocForm, ItemForm)
|
UploadSourceDocForm, SourceDocForm, ItemForm,
|
||||||
|
ForgotPasswordForm, PasswordForm)
|
||||||
from .model import User, SourceDoc, Item, XanaDoc, XanaLink
|
from .model import User, SourceDoc, Item, XanaDoc, XanaLink
|
||||||
from .url import get_url
|
from .url import get_url
|
||||||
from .edl import fulfil_edl_with_sources
|
from .edl import fulfil_edl_with_sources
|
||||||
|
@ -13,6 +14,7 @@ from werkzeug.debug.tbtools import get_current_traceback
|
||||||
from jinja2 import evalcontextfilter, Markup
|
from jinja2 import evalcontextfilter, Markup
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from .utils import nbsp_at_start
|
from .utils import nbsp_at_start
|
||||||
|
from itsdangerous import URLSafeTimedSerializer
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -60,6 +62,45 @@ def home():
|
||||||
docs = Item.query.order_by(Item.created)
|
docs = Item.query.order_by(Item.created)
|
||||||
return render_template('home.html', docs=docs)
|
return render_template('home.html', docs=docs)
|
||||||
|
|
||||||
|
@bp.route('/password_reset', methods=['GET', 'POST'])
|
||||||
|
def password_reset():
|
||||||
|
form = ForgotPasswordForm()
|
||||||
|
if not form.validate_on_submit():
|
||||||
|
return render_template('auth/password_reset.html', form=form)
|
||||||
|
ts = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
|
||||||
|
user = User.lookup_user_or_email(form.user_or_email.data)
|
||||||
|
if user:
|
||||||
|
token = ts.dumps(user.id, salt='password-reset')
|
||||||
|
print(token)
|
||||||
|
return redirect(url_for('.password_reset_sent'))
|
||||||
|
|
||||||
|
@bp.route('/password_reset/sent', methods=['GET', 'POST'])
|
||||||
|
def password_reset_sent():
|
||||||
|
return render_template('auth/password_reset_sent.html')
|
||||||
|
|
||||||
|
@bp.route('/reset/<token>', methods=['GET', 'POST'])
|
||||||
|
def reset_with_token(token):
|
||||||
|
ts = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
|
||||||
|
try:
|
||||||
|
user_id = ts.loads(token, salt='password-reset', max_age=86400)
|
||||||
|
except:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
form = PasswordForm()
|
||||||
|
if not form.validate_on_submit():
|
||||||
|
return render_template('auth/password_reset_confirm.html', form=form)
|
||||||
|
|
||||||
|
user = User.query.get(user_id)
|
||||||
|
user.set_password(form.password.data)
|
||||||
|
session.add(user)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return redirect(url_for('.password_reset_complete'))
|
||||||
|
|
||||||
|
@bp.route('/reset/done')
|
||||||
|
def password_reset_complete():
|
||||||
|
return render_template('auth/password_reset_complete.html')
|
||||||
|
|
||||||
@bp.route('/source_doc_upload', methods=["POST"])
|
@bp.route('/source_doc_upload', methods=["POST"])
|
||||||
@show_errors
|
@show_errors
|
||||||
def source_doc_upload():
|
def source_doc_upload():
|
||||||
|
|
Loading…
Reference in a new issue