🔐 Auth: інтеграція JWT в Memory Service + конфігурації
- Опціональна JWT auth в Memory Service endpoints - get_current_service_optional для backward compatibility - NATS auth config (nkeys) - шаблони - Qdrant auth config (API keys) - шаблони - Тестовий скрипт для повного потоку TODO: Генерація реальних JWT/ключів та застосування конфігів
This commit is contained in:
@@ -5,7 +5,7 @@ JWT Authentication для Memory Service
|
||||
import os
|
||||
import jwt
|
||||
import time
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
from fastapi import HTTPException, Security
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from app.config import get_settings
|
||||
@@ -42,8 +42,21 @@ def verify_jwt_token(token: str) -> dict:
|
||||
raise HTTPException(status_code=401, detail="Invalid token")
|
||||
|
||||
|
||||
async def get_current_service_optional(
|
||||
credentials: Optional[HTTPAuthorizationCredentials] = Security(security, auto_error=False)
|
||||
) -> Optional[dict]:
|
||||
"""Dependency для отримання поточного сервісу з JWT (опціонально)"""
|
||||
if not credentials:
|
||||
return None
|
||||
token = credentials.credentials
|
||||
try:
|
||||
payload = verify_jwt_token(token)
|
||||
return payload
|
||||
except HTTPException:
|
||||
return None
|
||||
|
||||
async def get_current_service(credentials: HTTPAuthorizationCredentials = Security(security)) -> dict:
|
||||
"""Dependency для отримання поточного сервісу з JWT"""
|
||||
"""Dependency для отримання поточного сервісу з JWT (обов'язково)"""
|
||||
token = credentials.credentials
|
||||
payload = verify_jwt_token(token)
|
||||
return payload
|
||||
|
||||
@@ -8,6 +8,7 @@ DAARION Memory Service - FastAPI Application
|
||||
"""
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import List, Optional
|
||||
from fastapi import Depends
|
||||
from uuid import UUID
|
||||
import structlog
|
||||
from fastapi import FastAPI, HTTPException, Query
|
||||
@@ -23,6 +24,7 @@ from .models import (
|
||||
)
|
||||
from .vector_store import vector_store
|
||||
from .database import db
|
||||
from .auth import get_current_service, get_current_service_optional
|
||||
|
||||
logger = structlog.get_logger()
|
||||
settings = get_settings()
|
||||
@@ -76,8 +78,12 @@ async def health():
|
||||
# ============================================================================
|
||||
|
||||
@app.post("/threads", response_model=ThreadResponse)
|
||||
async def create_thread(request: CreateThreadRequest):
|
||||
async def create_thread(
|
||||
request: CreateThreadRequest,
|
||||
service: Optional[dict] = Depends(get_current_service_optional)
|
||||
):
|
||||
"""Create new conversation thread"""
|
||||
# Auth опціональний: якщо JWT надано, перевіряємо; якщо ні - дозволяємо (dev режим)
|
||||
thread = await db.create_thread(
|
||||
org_id=request.org_id,
|
||||
user_id=request.user_id,
|
||||
@@ -123,7 +129,10 @@ async def list_threads(
|
||||
# ============================================================================
|
||||
|
||||
@app.post("/events", response_model=EventResponse)
|
||||
async def add_event(request: AddEventRequest):
|
||||
async def add_event(
|
||||
request: AddEventRequest,
|
||||
service: Optional[dict] = Depends(get_current_service_optional)
|
||||
):
|
||||
"""Add event to conversation (message, tool call, etc.)"""
|
||||
event = await db.add_event(
|
||||
thread_id=request.thread_id,
|
||||
@@ -158,7 +167,10 @@ async def get_events(
|
||||
# ============================================================================
|
||||
|
||||
@app.post("/memories", response_model=MemoryResponse)
|
||||
async def create_memory(request: CreateMemoryRequest):
|
||||
async def create_memory(
|
||||
request: CreateMemoryRequest,
|
||||
service: Optional[dict] = Depends(get_current_service_optional)
|
||||
):
|
||||
"""Create long-term memory item"""
|
||||
# Create in PostgreSQL
|
||||
memory = await db.create_memory(
|
||||
|
||||
Reference in New Issue
Block a user