gateway/modules/routes/routeGeneral.py
2025-05-22 00:48:56 +02:00

132 lines
4.8 KiB
Python

from fastapi import APIRouter, HTTPException, Depends, Body, status, Response
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse, JSONResponse
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.staticfiles import StaticFiles
from typing import Dict, Any, Optional
from datetime import timedelta
import pathlib
import os
import logging
from pathlib import Path as FilePath
from modules.shared.configuration import APP_CONFIG
import modules.security.auth as auth
import modules.interfaces.gatewayInterface as gatewayInterface
router = APIRouter(
prefix="",
tags=["General"],
responses={404: {"description": "Not found"}}
)
# Static folder setup - using absolute path from app root
baseDir = FilePath(__file__).parent.parent.parent # Go up to gateway root
staticFolder = baseDir / "static"
os.makedirs(staticFolder, exist_ok=True)
# Mount static files
router.mount("/static", StaticFiles(directory=str(staticFolder), html=True), name="static")
logger = logging.getLogger(__name__)
@router.get("/", tags=["General"])
async def root():
"""API status endpoint"""
return {
"status": "online",
"message": "Data Platform API is active",
"allowedOrigins": f"Allowed origins are {APP_CONFIG.get('APP_ALLOWED_ORIGINS')}"
}
@router.get("/api/environment", tags=["General"])
async def get_environment():
"""Get environment configuration for frontend"""
return {
"apiBaseUrl": APP_CONFIG.get("APP_API_URL", ""),
"environment": APP_CONFIG.get("APP_ENV", "development"),
"instanceLabel": APP_CONFIG.get("APP_ENV_LABEL", "Development"),
# Add other environment variables the frontend might need
}
@router.options("/{fullPath:path}", tags=["General"])
async def options_route(fullPath: str):
return Response(status_code=200)
@router.post("/api/token", response_model=gatewayModel.Token, tags=["General"])
async def login_for_access_token(
formData: OAuth2PasswordRequestForm = Depends(),
authority: str = "local",
external_token: Optional[str] = None
):
"""Get access token for user authentication"""
# Create a new gateway interface instance with admin context
interfaceRoot = gatewayInterface.getRootInterface()
try:
# Get token directly
token = interfaceRoot.authenticateAndGetToken(
username=formData.username,
password=formData.password,
authority=authority,
external_token=external_token
)
return token
except ValueError as e:
# Handle authentication errors
error_msg = str(e)
logger.warning(f"Authentication failed for user {formData.username}: {error_msg}")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=error_msg,
headers={"WWW-Authenticate": "Bearer"},
)
except Exception as e:
# Handle other errors
error_msg = f"Login failed: {str(e)}"
logger.error(f"Unexpected error during login for user {formData.username}: {error_msg}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=error_msg
)
@router.get("/api/user/me", response_model=Dict[str, Any], tags=["General"])
async def read_user_me(currentUser: Dict[str, Any] = Depends(auth.getCurrentActiveUser)):
return currentUser
@router.post("/api/user/register", response_model=gatewayModel.User, tags=["General"])
async def register_user(userData: gatewayModel.User):
"""Register a new user."""
try:
interfaceRoot = gatewayInterface.getRootInterface()
return interfaceRoot.registerUser(userData.model_dump())
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"Error registering user: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to register user: {str(e)}"
)
@router.get("/api/user/available", response_model=Dict[str, Any], tags=["General"])
async def check_username_availability(
username: str,
authenticationAuthority: str = "local"
):
"""Check if a username is available for registration"""
try:
interfaceRoot = gatewayInterface.getRootInterface()
return interfaceRoot.checkUsernameAvailability(username, authenticationAuthority)
except Exception as e:
logger.error(f"Error checking username availability: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to check username availability: {str(e)}"
)
@router.get("/favicon.ico", tags=["General"])
async def favicon():
return FileResponse(str(staticFolder / "favicon.ico"), media_type="image/x-icon")