131 lines
3.3 KiB
Python
131 lines
3.3 KiB
Python
from flask import (
|
|
Blueprint, render_template, request, redirect, url_for, flash, session
|
|
)
|
|
from ..models import Users, Sessions
|
|
from ..constants import InfoboxKind, PermissionLevel
|
|
from ..auth import digest, verify
|
|
import secrets
|
|
import time
|
|
import re
|
|
|
|
bp = Blueprint("users", __name__, url_prefix = "/users/")
|
|
|
|
|
|
def is_logged_in():
|
|
return "pyrom_session_key" in session
|
|
|
|
|
|
def get_active_user():
|
|
if not is_logged_in():
|
|
return None
|
|
sess = Sessions.find({"key": session["pyrom_session_key"]})
|
|
if not sess:
|
|
return None
|
|
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")
|
|
|
|
|
|
@bp.post("/log_in")
|
|
def log_in_post():
|
|
target_user = Users.find({
|
|
"username": request.form['username']
|
|
})
|
|
if not target_user:
|
|
flash("Incorrect username or password.", InfoboxKind.ERROR)
|
|
return redirect(url_for("users.log_in"))
|
|
|
|
if not verify(target_user.password_hash, request.form['password']):
|
|
flash("Incorrect username or password.", InfoboxKind.ERROR)
|
|
return redirect(url_for("users.log_in"))
|
|
|
|
session_obj = create_session(target_user.id)
|
|
|
|
session['pyrom_session_key'] = session_obj.key
|
|
flash("Logged in!", InfoboxKind.INFO)
|
|
return redirect(url_for("users.log_in"))
|
|
|
|
|
|
@bp.get("/sign_up")
|
|
def sign_up():
|
|
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("/<username>")
|
|
def page(username):
|
|
return "stub"
|
|
|
|
|
|
@bp.get("/<username>/setings")
|
|
def settings(username):
|
|
return "stub"
|
|
|
|
|
|
@bp.get("/<username>/inbox")
|
|
def inbox(username):
|
|
return "stub"
|
|
|
|
|
|
@bp.get("/list")
|
|
def user_list():
|
|
return "stub"
|