diff --git a/app/routes/app.py b/app/routes/app.py index 67b0e87..bef5e5a 100644 --- a/app/routes/app.py +++ b/app/routes/app.py @@ -1,7 +1,7 @@ -from flask import Blueprint +from flask import Blueprint, redirect, url_for bp = Blueprint("app", __name__, url_prefix = "/") @bp.route("/") -def hello_world(): - return f"" +def index(): + return redirect(url_for("topics.all_topics")) diff --git a/app/routes/users.py b/app/routes/users.py index 218fab5..e83961a 100644 --- a/app/routes/users.py +++ b/app/routes/users.py @@ -2,10 +2,11 @@ from flask import ( Blueprint, render_template, request, redirect, url_for, flash, session ) from ..models import Users, Sessions -from ..constants import InfoboxKind +from ..constants import InfoboxKind, PermissionLevel from ..auth import digest, verify import secrets import time +import re bp = Blueprint("users", __name__, url_prefix = "/users/") @@ -23,6 +24,24 @@ def get_active_user(): return Users.find({"id": sess.user_id}) +def create_session(user_id): + return Sessions.create({ + "key": secrets.token_hex(16), + "user_id": user_id, + "expires_at": int(time.time()) + 30 * 24 * 60 * 60, + }) + + +def validate_password(password): + pattern = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_])(?!.*\s).{10,255}$' + return bool(re.fullmatch(pattern, password)) + + +def validate_username(username): + pattern = r'^[a-zA-Z0-9_-]{3,20}$' + return bool(re.fullmatch(pattern, username)) + + @bp.get("/log_in") def log_in(): return render_template("users/log_in.html") @@ -41,11 +60,7 @@ def log_in_post(): flash("Incorrect username or password.", InfoboxKind.ERROR) return redirect(url_for("users.log_in")) - session_obj = Sessions.create({ - "key": secrets.token_hex(16), - "user_id": target_user.id, - "expires_at": int(time.time()) + 30 * 24 * 60 * 60, - }) + session_obj = create_session(target_user.id) session['pyrom_session_key'] = session_obj.key flash("Logged in!", InfoboxKind.INFO) @@ -54,7 +69,45 @@ def log_in_post(): @bp.get("/sign_up") def sign_up(): - return "not yet" + return render_template("users/sign_up.html") + + +@bp.post("/sign_up") +def sign_up_post(): + username = request.form['username'] + password = request.form['password'] + password_confirm = request.form['password-confirm'] + + if not validate_username(username): + flash("Invalid username.", InfoboxKind.ERROR) + return redirect(url_for("users.sign_up")) + + user_exists = Users.count({"username": username}) > 0 + if user_exists: + flash(f"Username '{username}' is already taken.", InfoboxKind.ERROR) + return redirect(url_for("users.sign_up")) + + if not validate_password(password): + flash("Invalid password.", InfoboxKind.ERROR) + return redirect(url_for("users.sign_up")) + + if password != password_confirm: + flash("Passwords do not match.", InfoboxKind.ERROR) + return redirect(url_for("users.sign_up")) + + hashed = digest(password) + + new_user = Users.create({ + "username": username, + "password_hash": hashed, + "permission": PermissionLevel.GUEST.value, + }) + + session_obj = create_session(new_user.id) + + session['pyrom_session_key'] = session_obj.key + flash("Signed up successfully!", InfoboxKind.INFO) + return redirect(url_for("users.sign_up")) @bp.get("/") diff --git a/app/templates/users/log_in.html b/app/templates/users/log_in.html index f4e895a..2e91e03 100644 --- a/app/templates/users/log_in.html +++ b/app/templates/users/log_in.html @@ -2,7 +2,7 @@ {% block title %}Log in{% endblock %} {% block content %}
-

Log In

+

Log in



diff --git a/app/templates/users/sign_up.html b/app/templates/users/sign_up.html index e69de29..96f1a2a 100644 --- a/app/templates/users/sign_up.html +++ b/app/templates/users/sign_up.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} +{% block title %}Sign up{% endblock %} +{% block content %} +
+{% endblock %}