Add dynamic features: database models, authentication, and admin dashboard
This commit is contained in:
63
utils/auth.py
Normal file
63
utils/auth.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authentication Utilities
|
||||
|
||||
from functools import wraps
|
||||
from quart import session, request, redirect, url_for, jsonify
|
||||
from typing import Optional
|
||||
from models.user import User
|
||||
|
||||
def login_required(f):
|
||||
"""Decorator to require login for a route"""
|
||||
@wraps(f)
|
||||
async def decorated_function(*args, **kwargs):
|
||||
if 'user_id' not in session:
|
||||
if request.is_json:
|
||||
return jsonify({'error': 'Login required'}), 401
|
||||
return redirect(url_for('auth.login'))
|
||||
return await f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
def admin_required(f):
|
||||
"""Decorator to require admin role for a route"""
|
||||
@wraps(f)
|
||||
async def decorated_function(*args, **kwargs):
|
||||
if 'user_id' not in session:
|
||||
if request.is_json:
|
||||
return jsonify({'error': 'Login required'}), 401
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
user = await get_current_user()
|
||||
if not user or not user.is_admin:
|
||||
if request.is_json:
|
||||
return jsonify({'error': 'Admin access required'}), 403
|
||||
return redirect(url_for('home.index'))
|
||||
|
||||
return await f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
async def get_current_user() -> Optional[User]:
|
||||
"""Get the currently logged-in user"""
|
||||
if 'user_id' not in session:
|
||||
return None
|
||||
|
||||
try:
|
||||
user_id = session['user_id']
|
||||
return await User.find_by_id(user_id)
|
||||
except:
|
||||
# Clear invalid session
|
||||
session.pop('user_id', None)
|
||||
return None
|
||||
|
||||
def login_user(user: User):
|
||||
"""Log in a user (set session)"""
|
||||
session['user_id'] = user.id
|
||||
session['username'] = user.username
|
||||
session['is_admin'] = user.is_admin
|
||||
|
||||
def logout_user():
|
||||
"""Log out the current user (clear session)"""
|
||||
session.pop('user_id', None)
|
||||
session.pop('username', None)
|
||||
session.pop('is_admin', None)
|
||||
Reference in New Issue
Block a user