feat: MTG database integration with Redis caching

- Added MTG card ORM models (mtg_cards, mtg_sets tables)
- Created card_database service with search, get_by_name, get_by_set
- Added Redis client with caching layer (3600s TTL default)
- Created card router with caching on all endpoints:
  - Search cards (5min cache)
  - Get card by name (10min cache)
  - Get cards by set (15min cache)
  - Get card types/rarities (30min cache)
  - Get sets (1hr cache)
  - Get statistics (1hr cache)
- Updated settings.py:
  - Added JWT_SECRET_KEY field
  - Added DB_CONFIG and REDIS_CONFIG dictionaries
- Updated security.py to use JWT_SECRET_KEY with fallback
- Updated auth.py to use timezone-aware datetimes
- Updated refresh_mtg.py to use settings instead of os.environ
- Updated mtg_monitor.py to use settings for connections
- Added services package with __init__.py

All 20 tests passing.
This commit is contained in:
2026-07-18 18:41:05 +00:00
parent 167a352d44
commit 915242b330
20 changed files with 1804 additions and 287 deletions
+13 -3
View File
@@ -39,6 +39,9 @@ def create_access_token(
minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES
)
# Use JWT_SECRET_KEY if available, fall back to SECRET_KEY
secret = getattr(settings, 'JWT_SECRET_KEY', None) or settings.SECRET_KEY
payload = {
"sub": subject,
"exp": expire,
@@ -46,7 +49,7 @@ def create_access_token(
"type": "access",
"privlevel": privlevel,
}
return jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
return jwt.encode(payload, secret, algorithm=settings.JWT_ALGORITHM)
def create_refresh_token(subject: str, privlevel: str = "User") -> str:
@@ -54,6 +57,10 @@ def create_refresh_token(subject: str, privlevel: str = "User") -> str:
expire = datetime.now(timezone.utc) + timedelta(
days=settings.JWT_REFRESH_TOKEN_EXPIRE_DAYS
)
# Use JWT_SECRET_KEY if available, fall back to SECRET_KEY
secret = getattr(settings, 'JWT_SECRET_KEY', None) or settings.SECRET_KEY
payload = {
"sub": subject,
"exp": expire,
@@ -61,15 +68,18 @@ def create_refresh_token(subject: str, privlevel: str = "User") -> str:
"type": "refresh",
"privlevel": privlevel,
}
return jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
return jwt.encode(payload, secret, algorithm=settings.JWT_ALGORITHM)
def decode_token(token: str) -> Optional[dict]:
"""Decode and validate a JWT token."""
try:
# Use JWT_SECRET_KEY if available, fall back to SECRET_KEY
secret = getattr(settings, 'JWT_SECRET_KEY', None) or settings.SECRET_KEY
payload = jwt.decode(
token,
settings.SECRET_KEY,
secret,
algorithms=[settings.JWT_ALGORITHM],
)
return payload