synapse / backend /app /api /deps.py
adwitiyashukla's picture
updated code
48954a5
Raw
History Blame Contribute Delete
3.57 kB
from typing import Annotated
from fastapi import Depends, HTTPException, Request, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.ext.asyncio import AsyncSession
from app.config import get_settings
from app.core.quota import DailyQuota
from app.core.ratelimit import SlidingWindowLimiter, client_key, enforce
from app.core.security import decode_token
from app.database import get_db
from app.models import ChatSession, User
settings = get_settings()
bearer_scheme = HTTPBearer(auto_error=False)
HOUR = 3600
auth_limiter = SlidingWindowLimiter(
settings.rate_limit_auth, settings.rate_limit_window_seconds
)
chat_limiter = SlidingWindowLimiter(
settings.rate_limit_chat, settings.rate_limit_window_seconds
)
demo_session_limiter = SlidingWindowLimiter(settings.demo_sessions_per_hour, HOUR)
demo_chat_limiter = SlidingWindowLimiter(settings.demo_messages_per_hour, HOUR)
demo_daily_quota = DailyQuota(settings.demo_daily_message_cap)
async def get_current_user(
credentials: Annotated[
HTTPAuthorizationCredentials | None, Depends(bearer_scheme)
],
db: Annotated[AsyncSession, Depends(get_db)],
) -> User:
if credentials is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not authenticated",
headers={"WWW-Authenticate": "Bearer"},
)
user_id = decode_token(credentials.credentials, expected_type="access")
if user_id is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired token",
headers={"WWW-Authenticate": "Bearer"},
)
user = await db.get(User, user_id)
if user is None or not user.is_active:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found"
)
return user
CurrentUser = Annotated[User, Depends(get_current_user)]
DB = Annotated[AsyncSession, Depends(get_db)]
async def get_owned_session(
session_id: str, user: CurrentUser, db: DB
) -> ChatSession:
session = await db.get(ChatSession, session_id)
if session is None or session.user_id != user.id:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found"
)
return session
def rate_limit_auth(request: Request) -> None:
enforce(auth_limiter, request)
def rate_limit_chat(request: Request) -> None:
enforce(chat_limiter, request)
if not settings.demo_mode:
return
if not demo_chat_limiter.check(client_key(request)):
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail=(
f"Demo limit reached: {settings.demo_messages_per_hour} messages "
"per hour. Run Synapse locally from the GitHub repo for unlimited use."
),
)
if not demo_daily_quota.try_consume():
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail=(
"The shared demo has reached its daily message budget. "
"Please try again tomorrow, or run Synapse locally with your own key."
),
)
def rate_limit_demo_session(request: Request) -> None:
if not demo_session_limiter.check(client_key(request)):
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Too many demo sessions from this address. Please try again later.",
)