hack-wpi-python/goathacks/registration/__init__.py
Cara Salter 60953074e7
registration: Basic password reset
I think expiration should be pending on a proper way to do recurring
tasks -- I'm personally in favor of a CLI command that can be run from a
cronjob or systemd timer that will do things like auto-expire password
reset requests and send the daily registration reports.

Now that I'm thinking about it, this does need at least a rudimentary
system to make sure that it actually expires. If the expiration is
invalid at the time of reset, then the request can just be invalidated
and deleted. There's no pressing need for automatic removal until it's
implemented.

Thoughts @willhockey20?
2023-01-03 17:43:17 -05:00

157 lines
5.5 KiB
Python

from datetime import datetime
from flask import Blueprint, abort, config, current_app, flash, redirect, render_template, request, url_for
import flask_login
from flask_login import current_user
from goathacks.registration.forms import LoginForm, PwResetForm, RegisterForm, ResetForm
from werkzeug.security import check_password_hash, generate_password_hash
from flask_mail import Message
import ulid
from goathacks import db, mail as app_mail
from goathacks.models import PwResetRequest, User
bp = Blueprint('registration', __name__, url_prefix="/registration")
@bp.route("/", methods=["GET", "POST"])
def register():
if current_user.is_authenticated:
flash("You are already registered and logged in!")
print("got register")
form = RegisterForm(request.form)
print(vars(form.gender))
if request.method == 'POST':
print("Got form")
email = request.form.get('email')
first_name = request.form.get('first_name')
last_name = request.form.get('last_name')
password = request.form.get('password')
password_c = request.form.get('password_confirm')
school = request.form.get('school')
phone = request.form.get('phone_number')
gender = request.form.get('gender')
if password == password_c:
# Passwords match!
# Count of all non-waitlisted hackers
num_not_waitlisted = len(User.query.filter_by(waitlisted=False).all())
waitlisted = False
print(num_not_waitlisted)
print(current_app.config['MAX_BEFORE_WAITLIST'])
if num_not_waitlisted >= current_app.config['MAX_BEFORE_WAITLIST']:
waitlisted = True
user = User(
email=email,
password=generate_password_hash(password),
first_name=first_name,
last_name=last_name,
last_login=datetime.now(),
waitlisted=waitlisted,
school=school,
phone=phone,
gender=gender
)
db.session.add(user)
db.session.commit()
flask_login.login_user(user)
if waitlisted:
msg = Message("Goathacks - Waitlist Confirmation")
else:
msg = Message("GoatHacks - Registration Confirmation")
msg.add_recipient(user.email)
msg.sender = ("GoatHacks Team", "hack@wpi.edu")
msg.body = render_template("emails/registration.txt", user=user)
app_mail.send(msg)
return redirect(url_for("dashboard.home"))
else:
flash("Passwords do not match")
return render_template("register.html", form=form)
@bp.route("/login", methods=["GET", "POST"])
def login():
form = LoginForm(request.form)
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user == None:
flash("Email or password incorrect")
return render_template("login.html", form=form)
if check_password_hash(user.password, password):
flask_login.login_user(user)
flash("Welcome back!")
return redirect(url_for("dashboard.home"))
else:
flash("Incorrect password")
return render_template("login.html", form=form)
@bp.route("/reset", methods=["GET", "POST"])
def reset():
form = ResetForm(request.form)
if request.method == 'POST':
email = request.form.get('email')
user = User.query.filter_by(email=email).first()
if user == None:
flash("If that email has an account here, we've just sent it a link to reset your password.")
return redirect(url_for("registration.login"))
else:
r = PwResetRequest(
id=str(ulid.ulid()),
user_id=user.id
)
db.session.add(r)
db.session.commit()
msg = Message("GoatHacks - Password Reset Request")
msg.add_recipient(user.email)
msg.body = render_template("emails/password_reset.txt", code=r.id)
app_mail.send(msg)
flash("If that email has an account here, we've just sent it a link to reset your password.")
return redirect(url_for("registration.login"))
else:
return render_template("pw_reset.html", form=form)
@bp.route("/reset/complete/<string:id>", methods=["GET", "POST"])
def do_reset(id):
form = PwResetForm(request.form)
req = PwResetRequest.query.filter_by(id=id).first()
if req == None:
flash("Invalid request")
return redirect(url_for("registration.login"))
if request.method == "POST":
password = request.form.get("password")
password_c = request.form.get("password_confirm")
if password == password_c:
user = User.query.filter_by(id=req.user_id).first()
if user == None:
flash("Invalid user")
return redirect(url_for("registration.login"))
user.password = generate_password_hash(password)
db.session.delete(req)
db.session.commit()
flash("Password successfully reset")
return redirect(url_for("registration.login"))
else:
flash("Passwords do not match!")
return render_template("password_reset.html", form=form)
else:
return render_template("password_reset.html", form=form)