feat(B-RL): Rate-Limiting Konsistenz — zentrale Policies für Auth/AI/Upload/Webhook
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
B-RL: Rate-Limiting auf zentrale check_rate_limit() umgestellt - forgejo_error_reporter: In-Memory → zentrale Redis-Rate-Limit - ai_proactive: eigene Redis-Logik → zentrale check_rate_limit() - agent_runner: DB-basiertes Limit bleibt (zählt echte Ausführungen) - RateLimitPolicy Enum (AUTH/AI/UPLOAD/WEBHOOK) + check_rate_limit_policy() - 8 neue config.py Settings für Policy-Limits - 12 Routes mit Policies versehen (login, password-reset, AI, uploads, webhooks) Tests: 20 Tests in test_rate_limit_policies.py — alle grün - Policies, check_rate_limit, reset, get_client_ip, forgejo, ai_proactive - Keine Regression: 116 bestehende Tests grün
This commit is contained in:
+17
-15
@@ -10,7 +10,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.config import get_settings
|
||||
from app.core.auth import get_redis
|
||||
from app.core.db import get_auth_db
|
||||
from app.core.rate_limit import check_rate_limit, get_client_ip, reset_rate_limit
|
||||
from app.core.rate_limit import (
|
||||
RateLimitPolicy,
|
||||
check_rate_limit_policy,
|
||||
get_client_ip,
|
||||
reset_rate_limit,
|
||||
)
|
||||
from app.schemas.auth import (
|
||||
AuthResponse,
|
||||
LoginRequest,
|
||||
@@ -36,11 +41,10 @@ async def login(
|
||||
ip = get_client_ip(request)
|
||||
redis = get_redis()
|
||||
|
||||
# Rate limit
|
||||
await check_rate_limit(
|
||||
f"auth:login:{ip}:{body.email}",
|
||||
settings.rate_limit_login_max,
|
||||
settings.rate_limit_login_window,
|
||||
# Rate limit — unified AUTH policy
|
||||
await check_rate_limit_policy(
|
||||
f"rate:auth:login:{ip}:{body.email}",
|
||||
RateLimitPolicy.AUTH,
|
||||
)
|
||||
|
||||
result = await auth_service.login(db, redis, body.email, body.password, body.tenant_slug)
|
||||
@@ -53,7 +57,7 @@ async def login(
|
||||
session_id, csrf_token, user, tenant, role = result
|
||||
|
||||
# Reset rate limit on success
|
||||
await reset_rate_limit(f"auth:login:{ip}:{body.email}")
|
||||
await reset_rate_limit(f"rate:auth:login:{ip}:{body.email}")
|
||||
|
||||
response = Response(status_code=status.HTTP_200_OK)
|
||||
response.set_cookie(
|
||||
@@ -217,10 +221,9 @@ async def password_reset_request(
|
||||
ip = get_client_ip(request)
|
||||
redis = get_redis() # noqa: F841
|
||||
|
||||
await check_rate_limit(
|
||||
f"auth:reset:{ip}",
|
||||
settings.rate_limit_reset_max,
|
||||
settings.rate_limit_reset_window,
|
||||
await check_rate_limit_policy(
|
||||
f"rate:auth:reset:{ip}",
|
||||
RateLimitPolicy.AUTH,
|
||||
)
|
||||
|
||||
await auth_service.request_password_reset(db, body.email)
|
||||
@@ -237,10 +240,9 @@ async def password_reset_confirm(
|
||||
ip = get_client_ip(request)
|
||||
redis = get_redis() # noqa: F841
|
||||
|
||||
await check_rate_limit(
|
||||
f"auth:reset_confirm:{ip}",
|
||||
settings.rate_limit_reset_confirm_max,
|
||||
settings.rate_limit_reset_confirm_window,
|
||||
await check_rate_limit_policy(
|
||||
f"rate:auth:reset_confirm:{ip}",
|
||||
RateLimitPolicy.AUTH,
|
||||
)
|
||||
|
||||
success = await auth_service.confirm_password_reset(db, body.token, body.new_password)
|
||||
|
||||
Reference in New Issue
Block a user