gateway/modules/routes/routeAttributes.py
2025-05-21 19:38:06 +02:00

113 lines
No EOL
3.8 KiB
Python

from fastapi import APIRouter, HTTPException, Depends, Path, Response
from typing import List, Dict, Any
from fastapi import status
import inspect
import importlib
import os
from pydantic import BaseModel
import logging
# Import auth module
import modules.security.auth as auth
# Import the attribute definition and helper functions
from modules.shared.defAttributes import AttributeDefinition, getModelAttributes
# Configure logger
logger = logging.getLogger(__name__)
# Create a response model for better documentation
class AttributeResponse(BaseModel):
"""Response model for entity attributes"""
attributes: List[AttributeDefinition]
class Config:
schema_extra = {
"example": {
"attributes": [
{
"name": "username",
"label": "Username",
"type": "string",
"required": True,
"placeholder": "Please enter username",
"editable": True,
"visible": True,
"order": 0
}
]
}
}
def getModelClasses() -> Dict[str, Any]:
"""Dynamically get all model classes from all model modules"""
modelClasses = {}
# Get the interfaces directory path
# Since we're in modules/routes/, we need to go up one level to modules/ then into interfaces/
interfaces_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'interfaces')
# Find all model files
for filename in os.listdir(interfaces_dir):
if filename.endswith('Model.py'):
# Convert filename to module name (e.g., gatewayModel.py -> gatewayModel)
module_name = filename[:-3]
# Import the module dynamically
module = importlib.import_module(f'modules.interfaces.{module_name}')
# Get all classes from the module
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, BaseModel) and obj != BaseModel:
modelClasses[name.lower()] = obj
return modelClasses
# Create a router for the attribute endpoints
router = APIRouter(
prefix="/api/attributes",
tags=["Attributes"],
responses={404: {"description": "Not found"}}
)
@router.get("/{entityType}", response_model=AttributeResponse)
async def get_entity_attributes(
entityType: str = Path(..., description="Type of entity (e.g. prompt)"),
currentUser: Dict[str, Any] = Depends(auth.getCurrentActiveUser)
):
"""
Retrieves the attribute definitions for a specific entity.
This can be used for dynamic form generation.
Parameters:
- entityType: The type of entity to get attributes for (e.g., 'user', 'prompt')
Returns:
- A list of attribute definitions that can be used to generate forms
"""
# Determine preferred language of the user
userLanguage = currentUser.get("language", "en")
# Get model classes dynamically
modelClasses = getModelClasses()
# Check if entity type is known
if entityType not in modelClasses:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Entity type '{entityType}' not found."
)
# Get model class and derive attributes from it
modelClass = modelClasses[entityType]
attributes = getModelAttributes(modelClass, userLanguage)
# Return only visible attributes
return AttributeResponse(attributes=[attr for attr in attributes if attr.visible])
@router.options("/{entityType}")
async def options_entity_attributes(
entityType: str = Path(..., description="Type of entity (e.g. prompt)")
):
"""Handle OPTIONS request for CORS preflight"""
return Response(status_code=200)