Files
myorg-assistant/src/api/app.py
Roger Oriol 87fb32b559 first commit
2026-02-03 23:50:19 +01:00

105 lines
3.2 KiB
Python

"""FastAPI application for web interface."""
from src.api.routes import dashboard, chat, tasks, calendar, projects
from fastapi import FastAPI, Request, Depends, HTTPException, status
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
from pathlib import Path
from src.config import settings
from src.api.agent_instance import agent
# Initialize FastAPI app
app = FastAPI(
title="MyOrg Assistant",
description="AI-powered personal assistant for GTD task management",
version="1.0.0",
)
# Set up templates and static files
BASE_DIR = Path(__file__).resolve().parent.parent
templates = Jinja2Templates(directory=str(BASE_DIR / "web" / "templates"))
app.mount("/static", StaticFiles(directory=str(BASE_DIR /
"web" / "static")), name="static")
# Security
security = HTTPBasic()
def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)) -> bool:
"""Verify HTTP Basic Auth credentials.
Args:
credentials: HTTP Basic credentials
Returns:
True if valid
Raises:
HTTPException: If credentials are invalid
"""
if not settings.web_password:
# No password set, allow access
return True
correct_password = settings.web_password.encode("utf8")
provided_password = credentials.password.encode("utf8")
is_correct = secrets.compare_digest(provided_password, correct_password)
if not is_correct:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect password",
headers={"WWW-Authenticate": "Basic"},
)
return True
# Import routes
# Include routers
app.include_router(dashboard.router, dependencies=[
Depends(verify_credentials)])
app.include_router(chat.router, dependencies=[Depends(verify_credentials)])
app.include_router(tasks.router, dependencies=[Depends(verify_credentials)])
app.include_router(calendar.router, dependencies=[Depends(verify_credentials)])
app.include_router(projects.router, dependencies=[Depends(verify_credentials)])
@app.get("/", response_class=HTMLResponse)
async def root(request: Request, _: bool = Depends(verify_credentials)):
"""Redirect to dashboard."""
from fastapi.responses import RedirectResponse
return RedirectResponse(url="/dashboard")
@app.get("/health")
async def health():
"""Health check endpoint."""
return {"status": "healthy", "service": "myorg-assistant"}
def run_web() -> None:
"""Run the web server."""
import uvicorn
print("🌐 Starting MyOrg Assistant Web Server...")
print(
f"📊 Dashboard: http://{settings.web_host}:{settings.web_port}/dashboard")
print(f"💬 Chat: http://{settings.web_host}:{settings.web_port}/chat")
if settings.web_password:
print("🔒 Authentication enabled")
else:
print("⚠️ Warning: No password set (WEB_PASSWORD not configured)")
uvicorn.run(
"src.api.app:app",
host=settings.web_host,
port=settings.web_port,
reload=False,
)