113 lines
5.2 KiB
Python
113 lines
5.2 KiB
Python
from surveyapp import mongo, bcrypt, mail
|
|
from flask import Flask, render_template, url_for, request, flash, redirect, Blueprint
|
|
# syntax for accessing files inside packages
|
|
from surveyapp.users.forms import (RegistrationForm, LoginForm,
|
|
UpdateAccountForm, RequestPasswordForm, PasswordResetForm)
|
|
from flask_login import current_user, login_user, logout_user, login_required
|
|
from surveyapp.models import User
|
|
from surveyapp.users.utils import send_email
|
|
|
|
|
|
users = Blueprint("users", __name__)
|
|
|
|
@users.route("/register", methods=["GET", "POST"])
|
|
def register():
|
|
form = RegistrationForm()
|
|
# Checks validation when form is submitted with submit button
|
|
if form.validate_on_submit():
|
|
# Decode with UTF-8 to make the hash a string rather than byte-code
|
|
password_hash = bcrypt.generate_password_hash(form.password.data).decode("utf-8")
|
|
# One user comment was to request the email validation to not be case sensitive. It is therefore saved in the database as lower case.
|
|
mongo.db.users.insert_one({\
|
|
"firstName" : form.first_name.data,\
|
|
"lastName" : form.last_name.data,\
|
|
"email" : form.email.data.lower(),\
|
|
"password" : password_hash})
|
|
flash("Account created successfully! You can now login.", "success")
|
|
return redirect(url_for("users.login"))
|
|
return render_template("users/register.html", title = "Register", form = form)
|
|
|
|
|
|
@users.route("/login", methods=["GET", "POST"])
|
|
def login():
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for("main.index"))
|
|
form = LoginForm()
|
|
if form.validate_on_submit():
|
|
user = mongo.db.users.find_one({"email": form.email.data.lower()})
|
|
if user and bcrypt.check_password_hash(user["password"], form.password.data):
|
|
user_obj = User(email=user["email"], first_name=user["firstName"], last_name=user["lastName"], _id=user["_id"])
|
|
# logs user into a session
|
|
login_user(user_obj, remember=form.remember.data)
|
|
# retrieve the page the user was attempting to access previously from the URL
|
|
next_page = request.args.get("next")
|
|
# and redirect them to that page (if it exists) using a ternary conditional
|
|
flash("Login successful.", "success")
|
|
return redirect(next_page) if next_page else redirect(url_for("main.index"))
|
|
else:
|
|
flash("Invalid username or password", "danger")
|
|
return render_template("users/login.html", title = "Login", form = form)
|
|
|
|
|
|
@users.route('/logout')
|
|
def logout():
|
|
logout_user()
|
|
flash("Logout successful.", "success")
|
|
return redirect(url_for('main.index'))
|
|
|
|
|
|
@users.route('/account', methods=["GET", "POST"])
|
|
@login_required
|
|
def account():
|
|
form = UpdateAccountForm()
|
|
if form.validate_on_submit():
|
|
# Update the 'current_user' object
|
|
current_user.first_name = form.first_name.data
|
|
current_user.last_name = form.last_name.data
|
|
current_user.email = form.email.data
|
|
# Update the user in the database
|
|
mongo.db.users.update_one({"_id": current_user._id},
|
|
{"$set": {"firstName": form.first_name.data,\
|
|
"lastName": form.last_name.data,\
|
|
"email": form.email.data.lower()}})
|
|
flash("Account details updated.", "success")
|
|
return redirect(url_for('users.account'))
|
|
form.first_name.data = current_user.first_name
|
|
form.last_name.data = current_user.last_name
|
|
form.email.data = current_user.email
|
|
return render_template("users/account.html", title = "Account", form = form)
|
|
|
|
|
|
@users.route('/reset_password', methods=["GET", "POST"])
|
|
def request_reset():
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for("main.index"))
|
|
form = RequestPasswordForm()
|
|
if form.validate_on_submit():
|
|
user = mongo.db.users.find_one({"email": form.email.data.lower()})
|
|
user_obj = User(email=user["email"], first_name=user["firstName"], last_name=user["lastName"], _id=user["_id"])
|
|
send_email(user_obj)
|
|
flash("An email has been sent with a password reset link", "success")
|
|
return redirect(url_for("users.login"))
|
|
return render_template("users/request_reset.html", title="Password Reset", form=form)
|
|
|
|
|
|
@users.route('/reset_password/<token>', methods=["GET", "POST"])
|
|
def reset_password(token):
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for("main.index"))
|
|
user = User.verify_reset_token(token)
|
|
if not user:
|
|
flash("That token is invalid or has expired", "warning")
|
|
return redirect(url_for("request_reset"))
|
|
form = PasswordResetForm()
|
|
if form.validate_on_submit():
|
|
# Decode with UTF-8 to make the hash a string rather than byte-code
|
|
password_hash = bcrypt.generate_password_hash(form.password.data).decode("utf-8")
|
|
# One user comment was to request the email validation to not be case sensitive. It is therefore saved in the database as lower case.
|
|
mongo.db.users.update_one({"_id": user["_id"]},
|
|
{"$set": {"password": password_hash}})
|
|
flash("Password updated! You can now login.", "success")
|
|
return redirect(url_for("users.login"))
|
|
return render_template("users/reset_password.html", title="Password Reset", form=form)
|