Move auth logic to blueprint

This commit is contained in:
Peter Stockings
2025-07-23 21:46:13 +10:00
parent b0a172bee0
commit 19d855fb89
6 changed files with 94 additions and 88 deletions

91
app.py
View File

@@ -4,9 +4,9 @@ from flask import Flask, Response, jsonify, redirect, render_template, render_te
import jinja_partials
from jinja2_fragments import render_block
import requests
from extensions import db, htmx, init_app
from extensions import db, htmx, init_app, login_manager
from services import create_http_function_view_model, create_http_functions_view_model
from flask_login import LoginManager, UserMixin, current_user, login_required, login_user, logout_user
from flask_login import current_user, login_required
from werkzeug.security import check_password_hash, generate_password_hash
import os
from dotenv import load_dotenv
@@ -15,6 +15,7 @@ from routes.test import test
from routes.home import home
from routes.http import http
from routes.llm import llm
from routes.auth import auth
from flask_apscheduler import APScheduler
import asyncio
import aiohttp
@@ -28,9 +29,8 @@ app = Flask(__name__)
app.config.from_pyfile('config.py')
app.secret_key = os.environ.get('SECRET_KEY', '2a661781919643cb8a5a8bc57642d99f')
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
login_manager.login_view = "auth.login"
jinja_partials.register_extensions(app)
# Remove scheduler configuration and initialization
@@ -41,21 +41,7 @@ app.register_blueprint(test, url_prefix='/test')
app.register_blueprint(home, url_prefix='/home')
app.register_blueprint(http, url_prefix='/http')
app.register_blueprint(llm, url_prefix='/llm')
class User(UserMixin):
def __init__(self, id, username, password_hash, created_at):
self.id = id
self.username = username
self.password_hash = password_hash
self.created_at = created_at
@staticmethod
def get(user_id):
user_data = db.get_user(int(user_id))
if user_data:
return User(id=str(user_data['id']), username=user_data['username'], password_hash=user_data['password_hash'], created_at=user_data['created_at'])
return None
app.register_blueprint(auth, url_prefix='/auth')
# Swith to inter app routing, which results in speed up from ~400ms to ~270ms
# https://stackoverflow.com/questions/76886643/linking-two-not-exposed-dokku-apps
@@ -186,7 +172,7 @@ def execute_http_function(user_id, function):
# Check if the function is public, if not check if the user is authenticated and owns the function
if not is_public:
if not current_user.is_authenticated:
return login_manager.unauthorized()
return redirect(url_for('auth.login', next=request.url))
if int(current_user.id) != user_id:
return jsonify({'error': 'Function belongs to another user'}), 404
@@ -244,71 +230,6 @@ def execute_http_function(user_id, function):
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template("login.html")
username = request.form.get('username')
password = request.form.get('password')
if not username or not password:
return render_template("login.html", error="Both username and password must be entered")
user_data = db.get_user_by_username(username)
if not user_data:
return render_template("login.html", error="User does not exist")
if not check_password_hash(user_data['password_hash'], password):
return render_template("login.html", error="Invalid username or password")
user = User(id=str(user_data['id']), username=user_data['username'], password_hash=user_data['password_hash'], created_at=user_data['created_at'])
# user should be an instance of your `User` class
login_user(user)
#flask.flash('Logged in successfully.')
next = request.args.get('next')
return redirect(next or url_for('home.index'))
@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == 'GET':
return render_template("signup.html")
username = request.form.get('username')
password = request.form.get('password')
if not username or not password:
return render_template("signup.html", error="Both username and password must be entered")
if len(username) < 10 or len(password) < 10:
return render_template("signup.html", error="Both username and password must be at least 10 characters long")
user = db.get_user_by_username(username)
if user:
return render_template("signup.html", error="User already exists")
hashed_password = generate_password_hash(password)
user_data = db.create_new_user(username, hashed_password)
user = User(id=str(user_data['id']), username=user_data['username'], password_hash=user_data['password_hash'], created_at=user_data['created_at'])
login_user(user)
return redirect(url_for('home.index'))
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(url_for('landing_page'))
@login_manager.user_loader
def load_user(user_id):
user_data = db.get_user(int(user_id))
if user_data:
return User(id=str(user_data['id']), username=user_data['username'], password_hash=user_data['password_hash'], created_at=user_data['created_at'])
return None
if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 5000.