Critical (all fixed): - bcrypt statt SHA-256 für Passwörter - API-Keys gehasht in DB, Plaintext nur einmalig zurückgegeben - DB-Session-Leak behoben (SessionLocal + try/finally, Depends(get_db)) - Admin-Check via is_admin-Spalte statt Hardcoded-Username - CORS: konfigurierbare Origins via ALLOWED_ORIGINS, kein Wildcard mit Credentials High (all fixed): - TOCTOU-Race: check_and_increment_quota mit SELECT FOR UPDATE atomar - Getrennte Tages-/Monatszähler in Usage + automatische Reset-Logik - Token-Zählung mit tiktoken (cl100k_base) statt .split() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
88 lines
2.2 KiB
Python
88 lines
2.2 KiB
Python
import pytest
|
|
from fastapi.testclient import TestClient
|
|
import tempfile
|
|
import os
|
|
from pathlib import Path
|
|
|
|
def create_test_db():
|
|
"""Create a temporary SQLite database for tests."""
|
|
temp_db = tempfile.NamedTemporaryFile(suffix='.db', delete=False)
|
|
temp_db.close()
|
|
os.environ["DATABASE_URL"] = f"sqlite:///{temp_db.name}"
|
|
return temp_db.name
|
|
|
|
def cleanup_test_db(db_path):
|
|
"""Remove the temporary database."""
|
|
if os.path.exists(db_path):
|
|
os.unlink(db_path)
|
|
os.environ.pop("DATABASE_URL", None)
|
|
|
|
def setup_test_db():
|
|
"""Setup test database with required data."""
|
|
from database import Base, engine, SessionLocal
|
|
from models import User, APIKey, Quota, Usage
|
|
from crud import create_api_key, hash_password
|
|
|
|
# Create tables
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
db = SessionLocal()
|
|
|
|
# Create test user
|
|
test_user = User(
|
|
username="testuser",
|
|
email="test@example.com",
|
|
hashed_password=hash_password("test123"),
|
|
is_active=True
|
|
)
|
|
db.add(test_user)
|
|
db.commit()
|
|
db.refresh(test_user)
|
|
|
|
# Create API key for test user
|
|
_, raw_key = create_api_key(db, test_user.id, "test-key")
|
|
os.environ["TEST_API_KEY"] = raw_key
|
|
|
|
# Create admin user
|
|
admin_user = User(
|
|
username="admin",
|
|
email="admin@example.com",
|
|
hashed_password=hash_password("admin123"),
|
|
is_active=True,
|
|
is_admin=True,
|
|
)
|
|
db.add(admin_user)
|
|
db.commit()
|
|
db.refresh(admin_user)
|
|
|
|
# Create admin API key
|
|
_, admin_raw_key = create_api_key(db, admin_user.id, "admin-key")
|
|
os.environ["ADMIN_API_KEY"] = admin_raw_key
|
|
|
|
db.close()
|
|
|
|
return raw_key, admin_raw_key
|
|
|
|
def teardown_test_db():
|
|
"""Clean up test database and environment."""
|
|
from database import engine
|
|
from models import Base
|
|
Base.metadata.drop_all(bind=engine)
|
|
|
|
os.environ.pop("TEST_API_KEY", None)
|
|
os.environ.pop("ADMIN_API_KEY", None)
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_client():
|
|
"""Create test client with test database."""
|
|
db_path = create_test_db()
|
|
setup_test_db()
|
|
|
|
from main import app
|
|
client = TestClient(app)
|
|
|
|
yield client
|
|
|
|
teardown_test_db()
|
|
cleanup_test_db(db_path)
|