|
16 | 16 | from flask import Flask, make_response, request, render_template, flash, redirect, Markup, jsonify, url_for, session
|
17 | 17 | from werkzeug.security import generate_password_hash, check_password_hash
|
18 | 18 | from dbms.models import user as userModel
|
19 |
| -from utils import allowed_to_register, is_blacklisted |
20 |
| -from forms import SignupForm, LoginForm, UpdateForm |
| 19 | +from utils import allowed_to_register, is_blacklisted, check_email |
| 20 | +from forms import SignupForm, LoginForm, UpdateForm, ForgotForm, PasswordResetForm |
21 | 21 | from flask_jwt_extended import create_access_token, \
|
22 | 22 | get_jwt_identity, jwt_required, \
|
23 | 23 | JWTManager, current_user, \
|
@@ -692,5 +692,115 @@ def fields_count_by_domain():
|
692 | 692 | }), 400
|
693 | 693 |
|
694 | 694 |
|
| 695 | +@app.route('/forgot-password', methods=['GET', 'POST']) |
| 696 | +@jwt_required(optional=True) |
| 697 | +@csrf.exempt |
| 698 | +def forgot_password(): |
| 699 | + app.config["WTF_CSRF_ENABLED"] = False |
| 700 | + user_agent = request.headers.get('User-Agent') |
| 701 | + postman_notebook_request = utils.check_non_web_user_agent(user_agent) |
| 702 | + |
| 703 | + # check if already logged in |
| 704 | + user = get_identity_if_logedin() |
| 705 | + if user: |
| 706 | + if not postman_notebook_request: |
| 707 | + return redirect(app.config['DEVELOPMENT_BASE_URL'] + '/home') |
| 708 | + elif postman_notebook_request: |
| 709 | + return jsonify({'message': 'Already logged in'}) |
| 710 | + |
| 711 | + form = ForgotForm() |
| 712 | + |
| 713 | + # POST |
| 714 | + if form.validate_on_submit(): |
| 715 | + # gets email and password |
| 716 | + email = form.email.data |
| 717 | + |
| 718 | + # check account exists |
| 719 | + user = userModel.User.query \ |
| 720 | + .filter_by(email=email) \ |
| 721 | + .first() |
| 722 | + if user: |
| 723 | + # create email |
| 724 | + token = generate_confirmation_token(email) |
| 725 | + url = url_for('reset_password', token=token, _external=True) |
| 726 | + html = render_template('reset-email.html', reset_url=url) |
| 727 | + subject = 'Reset password' |
| 728 | + |
| 729 | + # send email |
| 730 | + send_email(email, subject, html) |
| 731 | + |
| 732 | + # response |
| 733 | + msg = 'A link to reset your password has been sent to your email!' |
| 734 | + if postman_notebook_request: |
| 735 | + return jsonify({"message": msg}) |
| 736 | + else: |
| 737 | + flash(message=Markup(f'A password reset link has been sent to "{email}".'), category='info') |
| 738 | + else: |
| 739 | + # unregistered or unactivated account |
| 740 | + msg = 'Account does not exist!' |
| 741 | + if postman_notebook_request: |
| 742 | + return jsonify({"message": msg}) |
| 743 | + else: |
| 744 | + flash(message=Markup(f'A user with email "{email}" does not exist.'), category='info') |
| 745 | + |
| 746 | + # GET |
| 747 | + return render_template('forgot-password.html', form=form) |
| 748 | + |
| 749 | + |
| 750 | +@app.route('/reset-password/<token>', methods=['GET', 'POST']) |
| 751 | +@jwt_required(optional=True) |
| 752 | +@csrf.exempt |
| 753 | +def reset_password(token): |
| 754 | + app.config["WTF_CSRF_ENABLED"] = False |
| 755 | + user_agent = request.headers.get('User-Agent') |
| 756 | + postman_notebook_request = utils.check_non_web_user_agent(user_agent) |
| 757 | + |
| 758 | + # check if already logged in |
| 759 | + user = get_identity_if_logedin() |
| 760 | + if user: |
| 761 | + if not postman_notebook_request: |
| 762 | + return redirect(app.config['DEVELOPMENT_BASE_URL'] + '/home') |
| 763 | + elif postman_notebook_request: |
| 764 | + return jsonify({'message': 'Already logged in'}) |
| 765 | + |
| 766 | + try: |
| 767 | + # check if token is valid email |
| 768 | + email = confirm_token(token) |
| 769 | + |
| 770 | + # checking if user exists |
| 771 | + user = userModel.User.query \ |
| 772 | + .filter_by(email=email) \ |
| 773 | + .first() |
| 774 | + if user: |
| 775 | + form = PasswordResetForm() |
| 776 | + # POST |
| 777 | + if form.validate_on_submit(): |
| 778 | + # get new password |
| 779 | + password = form.password.data |
| 780 | + user_to_update = userModel.User.query.filter_by(email=email).first() |
| 781 | + |
| 782 | + user_to_update.password = generate_password_hash(password) |
| 783 | + db.session.commit() |
| 784 | + |
| 785 | + # response |
| 786 | + msg = 'Password updated succesfully!' |
| 787 | + if postman_notebook_request: |
| 788 | + return jsonify({"message": msg}) |
| 789 | + else: |
| 790 | + flash(message=Markup(f'Password for email "{email}" has been updated.'), category='info') |
| 791 | + return redirect(app.config['DEVELOPMENT_BASE_URL'] + '/') |
| 792 | + |
| 793 | + return render_template('reset-password.html', form=form) |
| 794 | + |
| 795 | + except: |
| 796 | + msg = 'The confirmation link is invalid or has expired.' |
| 797 | + if postman_notebook_request: |
| 798 | + return jsonify({"message": msg}) |
| 799 | + else: |
| 800 | + flash(message=msg, category='danger') |
| 801 | + return redirect(app.config['DEVELOPMENT_BASE_URL'] + '/forgot-password') |
| 802 | + |
| 803 | + |
| 804 | + |
695 | 805 | if __name__ == '__main__':
|
696 |
| - app.run(host='0.0.0.0') |
| 806 | + app.run(host='0.0.0.0', debug=True) |
0 commit comments