Update authentication system, database models, and UI components

This commit is contained in:
oib
2025-08-07 19:39:22 +02:00
parent d497492186
commit 72f79b1059
48 changed files with 5328 additions and 1642 deletions

94
auth.py
View File

@ -1,7 +1,7 @@
"""Authentication middleware and utilities for dicta2stream"""
from fastapi import Request, HTTPException, Depends, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlmodel import Session
from sqlmodel import Session, select
from typing import Optional
from models import User, Session as DBSession, verify_session
@ -11,40 +11,39 @@ security = HTTPBearer()
def get_current_user(
request: Request,
db: Session = Depends(get_db),
credentials: HTTPAuthorizationCredentials = Depends(security)
) -> User:
"""Dependency to get the current authenticated user"""
token = credentials.credentials
db_session = verify_session(db, token)
if not db_session:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired session",
headers={"WWW-Authenticate": "Bearer"},
)
# Get the user from the session
user = db.exec(
select(User).where(User.username == db_session.user_id)
).first()
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found",
headers={"WWW-Authenticate": "Bearer"},
)
# Attach the session to the request state for later use
request.state.session = db_session
return user
# Use the database session context manager
with get_db() as db:
db_session = verify_session(db, token)
if not db_session:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired session",
headers={"WWW-Authenticate": "Bearer"},
)
# Get the user from the session using query interface
user = db.query(User).filter(User.email == db_session.uid).first()
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found",
headers={"WWW-Authenticate": "Bearer"},
)
# Attach the session to the request state for later use
request.state.session = db_session
return user
def get_optional_user(
request: Request,
db: Session = Depends(get_db),
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security, use_cache=False)
) -> Optional[User]:
"""Dependency that returns the current user if authenticated, None otherwise"""
@ -52,22 +51,45 @@ def get_optional_user(
return None
try:
return get_current_user(request, db, credentials)
# get_current_user now handles its own database session
return get_current_user(request, credentials)
except HTTPException:
return None
def create_session(db: Session, user: User, request: Request) -> DBSession:
"""Create a new session for the user"""
user_agent = request.headers.get("user-agent")
def create_session(user: User, request: Request) -> DBSession:
"""Create a new session for the user (valid for 24 hours)"""
import secrets
from datetime import datetime, timedelta
user_agent = request.headers.get("user-agent", "")
ip_address = request.client.host if request.client else "0.0.0.0"
session = DBSession.create_for_user(
user_id=user.username,
# Create session token and set 24-hour expiry
session_token = secrets.token_urlsafe(32)
expires_at = datetime.utcnow() + timedelta(hours=24)
# Create the session object
session = DBSession(
token=session_token,
user_id=user.email,
ip_address=ip_address,
user_agent=user_agent
user_agent=user_agent,
expires_at=expires_at,
is_active=True
)
db.add(session)
db.commit()
return session
# Use the database session context manager
with get_db() as db:
try:
db.add(session)
db.commit()
db.refresh(session) # Ensure we have the latest data
return session
except Exception as e:
db.rollback()
# Debug messages disabled
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to create session"
)