feat: multi-Oracle server support with runtime switching

Complete implementation of multi-server Oracle database support:

Backend:
- Multi-pool Oracle with lazy loading per server
- Email-to-server cache for automatic server discovery
- JWT tokens include server_id claim
- /auth/check-identity and /auth/check-email endpoints
- /auth/my-servers endpoint for listing user's accessible servers
- Server switch with password re-authentication

Frontend:
- New ServerSelector component for header dropdown
- Multi-step login flow (identity → server → password)
- Server switching from header with password modal
- Mobile drawer menu with server selection
- Dark mode support for all new components
- URL bookmark support with ?server= query param

Scripts:
- Unified start.sh replacing start-prod.sh/start-test.sh
- Unified ssh-tunnel.sh with multi-server support
- Updated status.sh for new architecture

Tests:
- E2E tests for multi-server and single-server login flows
- Backend unit tests for all new endpoints
- Oracle multi-pool integration tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-01-26 22:39:06 +00:00
parent 5f99ee2fd0
commit b137e80b71
102 changed files with 9398 additions and 2787 deletions

View File

@@ -13,6 +13,12 @@ from pydantic import BaseModel
from shared.auth.dependencies import get_current_user, CurrentUser
class AuthModeResponse(BaseModel):
"""Response for auth mode endpoint."""
mode: str # "single-server" or "multi-server"
supports_email_login: bool # True if email-based login is available
class LogEntry(BaseModel):
"""Single log entry."""
line: str
@@ -36,6 +42,36 @@ def create_system_router() -> APIRouter:
"""
router = APIRouter()
@router.get("/auth-mode", response_model=AuthModeResponse)
async def get_auth_mode():
"""
Get the authentication mode configuration.
This is a PUBLIC endpoint (no auth required) that tells the frontend
whether to use the email-based multi-server login flow or the classic
username/password single-server flow.
Returns:
- mode: "single-server" for legacy config, "multi-server" for ORACLE_SERVERS
- supports_email_login: True only in multi-server mode with email cache
"""
from backend.config import settings
servers = settings.get_oracle_servers()
# Multi-server mode: 2+ servers configured via ORACLE_SERVERS
if servers and len(servers) > 1:
return AuthModeResponse(
mode="multi-server",
supports_email_login=True
)
# Single-server mode: legacy config or single ORACLE_SERVERS entry
return AuthModeResponse(
mode="single-server",
supports_email_login=False
)
def get_logs_path() -> Path:
"""Get logs directory path based on environment."""
# Windows production: C:\inetpub\wwwroot\roa2web\logs