feat: Add optional web interface authentication with session management
Local Docker Build (Dev) / build-dev (pull_request) Successful in 3s
Local Docker Build (Dev) / build-dev (pull_request) Successful in 3s
Authentication Features: - Optional HTTP Basic Auth with session cookies for web interface protection - Configurable username/password with session timeout (default: 1 hour) - Selective route protection (web interface protected, webhooks/APIs remain public) - Authentication status display with logout functionality in web UI - Session cleanup and graceful logout with browser re-authentication prompt Configuration: - WEB_AUTH_ENABLED in .env (default: false - no breaking changes) - WEB_AUTH_USERNAME/WEB_AUTH_PASSWORD in .env.secrets - WEB_AUTH_SESSION_TIMEOUT configurable (5min-24h range) Development Tools: - Added debug_tv.py for TV series/episode debugging (series, season, episode levels) - Comprehensive episode data inspection with validation and sources breakdown - Complements existing debug_movie.py for complete media debugging coverage Technical Implementation: - SimpleAuthMiddleware with FastAPI integration - Session management with automatic cleanup - Authentication status API endpoints - Responsive CSS styling for auth UI elements - JavaScript functions for auth checking and logout
This commit is contained in:
+33
-1
@@ -7,7 +7,7 @@ import requests
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from fastapi import HTTPException, BackgroundTasks, Request
|
||||
from fastapi import HTTPException, BackgroundTasks, Request, Response
|
||||
from typing import Optional
|
||||
|
||||
# Import models
|
||||
@@ -1396,6 +1396,38 @@ def register_routes(app, dependencies: dict):
|
||||
"""Update episode dateadded"""
|
||||
return await update_episode_date(dependencies, imdb_id, season, episode, request.dateadded, request.source)
|
||||
|
||||
@app.post("/api/auth/logout")
|
||||
async def _logout(request: Request, response: Response):
|
||||
"""Logout endpoint - clears session"""
|
||||
session_manager = dependencies.get("session_manager")
|
||||
if session_manager:
|
||||
session_token = request.cookies.get("nfoguard_session")
|
||||
if session_token:
|
||||
session_manager.delete_session(session_token)
|
||||
|
||||
response.delete_cookie("nfoguard_session")
|
||||
return {"status": "logged_out", "message": "Session cleared"}
|
||||
|
||||
@app.get("/api/auth/status")
|
||||
async def _auth_status(request: Request):
|
||||
"""Check authentication status"""
|
||||
auth_enabled = dependencies.get("auth_enabled", False)
|
||||
|
||||
if not auth_enabled:
|
||||
return {"authenticated": True, "auth_enabled": False, "message": "Authentication disabled"}
|
||||
|
||||
session_manager = dependencies.get("session_manager")
|
||||
if not session_manager:
|
||||
return {"authenticated": False, "auth_enabled": True, "message": "Session manager not available"}
|
||||
|
||||
session_token = request.cookies.get("nfoguard_session")
|
||||
if session_token:
|
||||
username = session_manager.get_session_user(session_token)
|
||||
if username:
|
||||
return {"authenticated": True, "auth_enabled": True, "username": username}
|
||||
|
||||
return {"authenticated": False, "auth_enabled": True, "message": "Not authenticated"}
|
||||
|
||||
@app.post("/api/bulk/update-source")
|
||||
async def _bulk_update_source(request: BulkUpdateRequest):
|
||||
"""Bulk update source for movies or episodes"""
|
||||
|
||||
Reference in New Issue
Block a user