Files
BTC-Portfolio/btc-portfolio/backend/app/main.py
T
Jonathan 85455f3271 Security hardening: secrets, validation, Docker, and error handling
- Add root .gitignore to prevent btc_wallet.py (with RPC credentials) from being committed
- Load JWT SECRET_KEY from environment variable instead of hardcoded value
- Restrict CORS to explicit methods/headers instead of wildcards
- Add Pydantic Field validation (gt=0) to purchase amounts and user credentials
- Add logging to all silent exception handlers in btc.py
- Run backend and frontend Docker containers as non-root appuser
- Add .dockerignore for both backend and frontend
- Pass SECRET_KEY env var through docker-compose; add healthchecks to both services
- Update bcrypt from pinned 3.2.2 to >=4.0.0
- Capture error objects in frontend catch blocks; check admin delete response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 18:40:41 +01:00

49 lines
1.4 KiB
Python

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import text
from .database import engine, Base, SessionLocal
from .routes import users, purchases, stats, history, admin, candles
Base.metadata.create_all(bind=engine)
app = FastAPI(title="BTC Portfolio API")
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "http://localhost:3001"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],
)
app.include_router(users.router)
app.include_router(purchases.router)
app.include_router(stats.router)
app.include_router(history.router)
app.include_router(admin.router, prefix="/admin")
app.include_router(candles.router)
@app.on_event("startup")
def startup():
# Schema migration: add is_admin column if missing
with engine.connect() as conn:
cols = [r[1] for r in conn.execute(text("PRAGMA table_info(users)"))]
if "is_admin" not in cols:
conn.execute(text("ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT 0"))
conn.commit()
# Seed / refresh BTC candle data
from .services.candles import refresh_latest_candles
db = SessionLocal()
try:
refresh_latest_candles(db)
finally:
db.close()
@app.get("/")
def root():
return {"message": "BTC Portfolio API"}