Files
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

30 lines
867 B
Python

import os
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-insecure-key-change-me")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 # 1 day
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
def create_access_token(data: dict) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode["exp"] = expire
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
def decode_token(token: str) -> dict:
return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])