"""FlowDeck — Kanban léger intégré à Gitea.""" from __future__ import annotations import logging from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from starlette.middleware.sessions import SessionMiddleware from app.config import settings from app.db import init_db from app.middleware.csrf import CSRFMiddleware from app.routers import dashboard, board, notes, api, auth, webhooks from app.services.gitea_client import gitea # ── logging ── logging.basicConfig( level=getattr(logging, settings.log_level.upper(), logging.INFO), format="%(asctime)s [%(levelname)s] %(message)s", ) logger = logging.getLogger(__name__) # ── app ── app = FastAPI( title="FlowDeck", version="0.3.0", docs_url="/docs" if settings.log_level == "DEBUG" else None, redoc_url=None, ) # ── middleware (order matters) ── # Session (for OAuth2 state) app.add_middleware( SessionMiddleware, secret_key=settings.app_secret_key, max_age=3600, # 1 hour for OAuth state ) # CSRF protection app.add_middleware(CSRFMiddleware) # CORS for LAN access app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # ── routers ── app.include_router(auth.router) app.include_router(dashboard.router) app.include_router(board.router) app.include_router(notes.router) app.include_router(api.router) app.include_router(webhooks.router) # ── static ── app.mount("/static", StaticFiles(directory="static"), name="static") @app.on_event("startup") async def startup(): init_db() # Seed admin user for non-OAuth mode from app.db import get_conn with get_conn() as conn: conn.execute( "INSERT OR IGNORE INTO users (login, full_name, email, is_admin) VALUES ('admin', 'Admin', '', 1)" ) conn.commit() logger.info("FlowDeck v0.3.0 started on port %d", settings.app_port)