132 lines
4.8 KiB
Python
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")
|