add password reset
This commit is contained in:
		
							parent
							
								
									edbe2e2395
								
							
						
					
					
						commit
						ff4617196f
					
				| 
						 | 
				
			
			@ -17,7 +17,7 @@ class SignupForm(Form):
 | 
			
		|||
                        [InputRequired(), Email(),
 | 
			
		||||
                         Length(min=5, max=EMAIL_LEN)],
 | 
			
		||||
                        description="we never share your e-mail address")
 | 
			
		||||
    password = PasswordField('password',
 | 
			
		||||
    password = StringField('password',
 | 
			
		||||
                        [InputRequired(), Length(min=4, max=PASSWORD_LEN)])
 | 
			
		||||
 | 
			
		||||
    def validate_username(form, field):
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +51,12 @@ class LoginForm(Form):
 | 
			
		|||
            return False
 | 
			
		||||
 | 
			
		||||
class ForgotPasswordForm(Form):
 | 
			
		||||
    username_or_email = StringField('username or e-mail address',
 | 
			
		||||
                                    [InputRequired(), Length(max=EMAIL_LEN)])
 | 
			
		||||
    user_or_email = StringField('username or e-mail address',
 | 
			
		||||
                                [InputRequired(), Length(max=EMAIL_LEN)])
 | 
			
		||||
 | 
			
		||||
class PasswordForm(Form):
 | 
			
		||||
    password = PasswordField('new password',
 | 
			
		||||
                             [InputRequired(), Length(min=4, max=PASSWORD_LEN)])
 | 
			
		||||
 | 
			
		||||
class AccountSettingsForm(Form):
 | 
			
		||||
    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 %}
 | 
			
		||||
{{ render_field(form.user_or_email) }}
 | 
			
		||||
{{ 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 %}
 | 
			
		||||
 | 
			
		||||
{% include "form/simple.html" %}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
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,
 | 
			
		||||
                         login_required, LoginManager)
 | 
			
		||||
from .forms import (LoginForm, SignupForm, AccountSettingsForm,
 | 
			
		||||
                    UploadSourceDocForm, SourceDocForm, ItemForm)
 | 
			
		||||
                    UploadSourceDocForm, SourceDocForm, ItemForm,
 | 
			
		||||
                    ForgotPasswordForm, PasswordForm)
 | 
			
		||||
from .model import User, SourceDoc, Item, XanaDoc, XanaLink
 | 
			
		||||
from .url import get_url
 | 
			
		||||
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 functools import wraps
 | 
			
		||||
from .utils import nbsp_at_start
 | 
			
		||||
from itsdangerous import URLSafeTimedSerializer
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +62,45 @@ def home():
 | 
			
		|||
    docs = Item.query.order_by(Item.created)
 | 
			
		||||
    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"])
 | 
			
		||||
@show_errors
 | 
			
		||||
def source_doc_upload():
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue