From 878e303cc64743c7a0ccde912ff6084b990c771b Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Mon, 11 May 2026 21:22:55 +0200 Subject: [PATCH] feat: setup FastAPI main app with routers and test fixtures - Main FastAPI app with all routers included - CORS middleware for frontend - Test fixtures with in-memory SQLite database - Placeholder routers for future tasks --- backend/app/main.py | 25 ++++++++++++++++++++++-- backend/app/routers/backups.py | 4 ++++ backend/app/routers/dashboard.py | 4 ++++ backend/app/routers/executions.py | 4 ++++ backend/app/routers/settings.py | 4 ++++ backend/tests/conftest.py | 32 +++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 backend/app/routers/backups.py create mode 100644 backend/app/routers/dashboard.py create mode 100644 backend/app/routers/executions.py create mode 100644 backend/app/routers/settings.py create mode 100644 backend/tests/conftest.py diff --git a/backend/app/main.py b/backend/app/main.py index 3ed0fae..dd449f2 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,7 +1,8 @@ from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager from app.database import engine, Base -from app.routers import sources, jobs +from app.routers import sources, jobs, executions, backups, settings, dashboard @asynccontextmanager async def lifespan(app: FastAPI): @@ -9,7 +10,27 @@ async def lifespan(app: FastAPI): await conn.run_sync(Base.metadata.create_all) yield -app = FastAPI(title="Backup Tool API", lifespan=lifespan) +app = FastAPI( + title="Backup Tool API", + version="0.1.0", + lifespan=lifespan +) + +app.add_middleware( + CORSMiddleware, + allow_origins=["http://localhost:3000"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) app.include_router(sources.router) app.include_router(jobs.router) +app.include_router(executions.router) +app.include_router(backups.router) +app.include_router(settings.router) +app.include_router(dashboard.router) + +@app.get("/api/health") +async def health_check(): + return {"status": "healthy"} diff --git a/backend/app/routers/backups.py b/backend/app/routers/backups.py new file mode 100644 index 0000000..f7e24d7 --- /dev/null +++ b/backend/app/routers/backups.py @@ -0,0 +1,4 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/backups", tags=["backups"]) +# Will be implemented in later tasks diff --git a/backend/app/routers/dashboard.py b/backend/app/routers/dashboard.py new file mode 100644 index 0000000..7b1688a --- /dev/null +++ b/backend/app/routers/dashboard.py @@ -0,0 +1,4 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/dashboard", tags=["dashboard"]) +# Will be implemented in later tasks diff --git a/backend/app/routers/executions.py b/backend/app/routers/executions.py new file mode 100644 index 0000000..b080216 --- /dev/null +++ b/backend/app/routers/executions.py @@ -0,0 +1,4 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/executions", tags=["executions"]) +# Will be implemented in later tasks diff --git a/backend/app/routers/settings.py b/backend/app/routers/settings.py new file mode 100644 index 0000000..d4dc4e3 --- /dev/null +++ b/backend/app/routers/settings.py @@ -0,0 +1,4 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/settings", tags=["settings"]) +# Will be implemented in later tasks diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py new file mode 100644 index 0000000..73ff134 --- /dev/null +++ b/backend/tests/conftest.py @@ -0,0 +1,32 @@ +import pytest +import pytest_asyncio +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker +from app.database import Base, get_db +from app.main import app +from httpx import AsyncClient + +TEST_DATABASE_URL = "sqlite+aiosqlite:///./test.db" + +@pytest_asyncio.fixture +async def db(): + engine = create_async_engine(TEST_DATABASE_URL, echo=False) + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) + async with async_session() as session: + yield session + + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.drop_all) + await engine.dispose() + +@pytest_asyncio.fixture +async def client(db): + async def override_get_db(): + yield db + + app.dependency_overrides[get_db] = override_get_db + async with AsyncClient(app=app, base_url="http://test") as ac: + yield ac + app.dependency_overrides.clear()