113 lines
No EOL
3.8 KiB
Python
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) |