Fix openapi authorize (#8794)

This commit is contained in:
tofarr 2025-05-29 13:20:00 -06:00 committed by GitHub
parent fd52841842
commit 30d53f8df0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 48 additions and 40 deletions

View File

@ -0,0 +1,25 @@
import os
from fastapi import Depends, HTTPException, status
from fastapi.security import APIKeyHeader
_SESSION_API_KEY = os.getenv('SESSION_API_KEY')
_SESSION_API_KEY_HEADER = APIKeyHeader(name='X-Session-API-Key', auto_error=False)
def check_session_api_key(
session_api_key: str | None = Depends(_SESSION_API_KEY_HEADER),
):
"""
Check the session API key and throw an exception if incorrect. Having this as a dependency
means it appears in OpenAPI Docs
"""
if session_api_key != _SESSION_API_KEY:
raise HTTPException(status.HTTP_401_UNAUTHORIZED)
def get_dependencies() -> list[Depends]:
result = []
if _SESSION_API_KEY:
result.append(Depends(check_session_api_key))
return result

View File

@ -10,7 +10,6 @@ from openhands.server.middleware import (
InMemoryRateLimiter,
LocalhostCORSMiddleware,
RateLimitMiddleware,
SessionApiKeyMiddleware,
)
from openhands.server.static import SPAStaticFiles
@ -27,8 +26,4 @@ base_app.add_middleware(
)
base_app.middleware('http')(AttachConversationMiddleware(base_app))
session_api_key = os.getenv('SESSION_API_KEY')
if session_api_key:
base_app.middleware('http')(SessionApiKeyMiddleware(session_api_key))
app = socketio.ASGIApp(sio, other_asgi_app=base_app)

View File

@ -1,7 +1,6 @@
import asyncio
import os
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime, timedelta
from urllib.parse import urlparse
@ -206,22 +205,3 @@ class AttachConversationMiddleware(SessionMiddlewareInterface):
await self._detach_session(request)
return response
@dataclass
class SessionApiKeyMiddleware:
"""Middleware which ensures that all requests contain a header with the token given"""
session_api_key: str
async def __call__(
self, request: Request, call_next: RequestResponseEndpoint
) -> Response:
if request.method != 'OPTIONS' and request.url.path.startswith('/api'):
if self.session_api_key != request.headers.get('X-Session-API-Key'):
return JSONResponse(
{'code': 'invalid_session_api_key'},
status_code=status.HTTP_401_UNAUTHORIZED,
)
response = await call_next(request)
return response

View File

@ -5,9 +5,10 @@ from openhands.core.logger import openhands_logger as logger
from openhands.events.event_filter import EventFilter
from openhands.events.serialization.event import event_to_dict
from openhands.runtime.base import Runtime
from openhands.server.dependencies import get_dependencies
from openhands.server.shared import conversation_manager
app = APIRouter(prefix='/api/conversations/{conversation_id}')
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies())
@app.get('/config')

View File

@ -5,9 +5,10 @@ from openhands.core.logger import openhands_logger as logger
from openhands.events.async_event_store_wrapper import AsyncEventStoreWrapper
from openhands.events.serialization import event_to_dict
from openhands.server.data_models.feedback import FeedbackDataModel, store_feedback
from openhands.server.dependencies import get_dependencies
from openhands.utils.async_utils import call_sync_from_async
app = APIRouter(prefix='/api/conversations/{conversation_id}')
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies())
@app.post('/submit-feedback')

View File

@ -23,23 +23,20 @@ from openhands.events.observation import (
FileReadObservation,
)
from openhands.runtime.base import Runtime
from openhands.server.data_models.conversation_info import ConversationInfo
from openhands.server.dependencies import get_dependencies
from openhands.server.file_config import (
FILES_TO_IGNORE,
)
from openhands.server.shared import (
ConversationStoreImpl,
config,
conversation_manager,
)
from openhands.server.user_auth import get_user_id
from openhands.server.utils import get_conversation_store
from openhands.storage.conversation.conversation_store import ConversationStore
from openhands.storage.data_models.conversation_metadata import ConversationMetadata
from openhands.storage.data_models.conversation_status import ConversationStatus
from openhands.utils.async_utils import call_sync_from_async
app = APIRouter(prefix='/api/conversations/{conversation_id}')
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies())
@app.get(

View File

@ -15,6 +15,7 @@ from openhands.integrations.service_types import (
UnknownException,
User,
)
from openhands.server.dependencies import get_dependencies
from openhands.server.shared import server_config
from openhands.server.user_auth import (
get_access_token,
@ -22,7 +23,7 @@ from openhands.server.user_auth import (
get_user_id,
)
app = APIRouter(prefix='/api/user')
app = APIRouter(prefix='/api/user', dependencies=get_dependencies())
@app.get('/repositories', response_model=list[Repository])

View File

@ -22,6 +22,7 @@ from openhands.server.data_models.conversation_info import ConversationInfo
from openhands.server.data_models.conversation_info_result_set import (
ConversationInfoResultSet,
)
from openhands.server.dependencies import get_dependencies
from openhands.server.services.conversation import create_new_conversation
from openhands.server.shared import (
ConversationStoreImpl,
@ -47,7 +48,7 @@ from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.utils.async_utils import wait_all
from openhands.utils.conversation_summary import get_default_conversation_title
app = APIRouter(prefix='/api')
app = APIRouter(prefix='/api', dependencies=get_dependencies())
class InitSessionRequest(BaseModel):

View File

@ -10,6 +10,7 @@ from openhands.integrations.github.github_service import GithubServiceImpl
from openhands.integrations.gitlab.gitlab_service import GitLabServiceImpl
from openhands.integrations.provider import ProviderToken
from openhands.integrations.service_types import ProviderType
from openhands.server.dependencies import get_dependencies
from openhands.server.shared import ConversationStoreImpl, config
from openhands.server.user_auth import (
get_access_token,
@ -18,7 +19,7 @@ from openhands.server.user_auth import (
)
from openhands.storage.data_models.conversation_metadata import ConversationMetadata
mcp_server = FastMCP('mcp')
mcp_server = FastMCP('mcp', dependencies=get_dependencies())
async def save_pr_metadata(

View File

@ -4,10 +4,11 @@ from fastapi import APIRouter
from openhands.controller.agent import Agent
from openhands.security.options import SecurityAnalyzers
from openhands.server.dependencies import get_dependencies
from openhands.server.shared import config, server_config
from openhands.utils.llm import get_supported_llm_models
app = APIRouter(prefix='/api/options')
app = APIRouter(prefix='/api/options', dependencies=get_dependencies())
@app.get('/models', response_model=list[str])

View File

@ -5,6 +5,7 @@ from openhands.core.logger import openhands_logger as logger
from openhands.integrations.provider import PROVIDER_TOKEN_TYPE, CustomSecret
from openhands.integrations.service_types import ProviderType
from openhands.integrations.utils import validate_provider_token
from openhands.server.dependencies import get_dependencies
from openhands.server.settings import (
CustomSecretModel,
CustomSecretWithoutValueModel,
@ -21,7 +22,7 @@ from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.secrets.secrets_store import SecretsStore
from openhands.storage.settings.settings_store import SettingsStore
app = APIRouter(prefix='/api')
app = APIRouter(prefix='/api', dependencies=get_dependencies())
# =================================================

View File

@ -6,7 +6,9 @@ from fastapi import (
status,
)
app = APIRouter(prefix='/api/conversations/{conversation_id}')
from openhands.server.dependencies import get_dependencies
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies())
@app.route('/security/{path:path}', methods=['GET', 'POST', 'PUT', 'DELETE'])

View File

@ -6,6 +6,7 @@ from openhands.integrations.provider import (
PROVIDER_TOKEN_TYPE,
ProviderType,
)
from openhands.server.dependencies import get_dependencies
from openhands.server.routes.secrets import invalidate_legacy_secrets_store
from openhands.server.settings import (
GETSettingsModel,
@ -20,7 +21,7 @@ from openhands.storage.data_models.settings import Settings
from openhands.storage.secrets.secrets_store import SecretsStore
from openhands.storage.settings.settings_store import SettingsStore
app = APIRouter(prefix='/api')
app = APIRouter(prefix='/api', dependencies=get_dependencies())
@app.get(

View File

@ -4,8 +4,9 @@ from fastapi.responses import JSONResponse
from openhands.core.logger import openhands_logger as logger
from openhands.events.async_event_store_wrapper import AsyncEventStoreWrapper
from openhands.events.serialization import event_to_trajectory
from openhands.server.dependencies import get_dependencies
app = APIRouter(prefix='/api/conversations/{conversation_id}')
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies())
@app.get('/trajectory')