feat: initial commit - Phase 1 & 2 core features

This commit is contained in:
hiderfong
2026-04-22 17:07:33 +08:00
commit 1773bda06b
25005 changed files with 6252106 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import time
import json
from app.core.config import settings
from app.core.database import engine, Base
from app.core.events import init_minio_bucket
from app.api.v1 import api_router
from app.models import log as log_models
# Create tables (dev convenience; use Alembic in production)
Base.metadata.create_all(bind=engine)
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
description=settings.DESCRIPTION,
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.middleware("http")
async def log_requests(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
duration = int((time.time() - start_time) * 1000)
# Skip health checks
if request.url.path in ["/docs", "/openapi.json", "/redoc"]:
return response
from app.core.database import SessionLocal
try:
db = SessionLocal()
body_bytes = b""
if request.method in ["POST", "PUT", "PATCH"]:
try:
body_bytes = await request.body()
# Re-assign body for downstream
async def receive():
return {"type": "http.request", "body": body_bytes}
request._receive = receive
except Exception:
pass
log_entry = log_models.OperationLog(
module=request.url.path.split("/")[2] if len(request.url.path.split("/")) > 2 else "",
action=request.url.path,
method=request.method,
path=str(request.url),
ip=request.client.host if request.client else None,
status_code=response.status_code,
duration_ms=duration,
)
db.add(log_entry)
db.commit()
except Exception:
pass
finally:
db.close()
return response
@app.on_event("startup")
async def startup_event():
init_minio_bucket()
from app.core.database import SessionLocal
from app.services.user_service import create_initial_data
from app.services.classification_service import init_builtin_data
db = SessionLocal()
try:
create_initial_data(db)
init_builtin_data(db)
finally:
db.close()
@app.get("/health")
def health_check():
return {"status": "ok"}
app.include_router(api_router, prefix="/api/v1")