114 lines
3.9 KiB
Python
114 lines
3.9 KiB
Python
# Standards API routes
|
|
from fastapi import APIRouter, UploadFile, File, HTTPException, Query
|
|
from typing import List, Optional
|
|
from loguru import logger
|
|
|
|
from app.core.models import Standard, StandardUploadResponse
|
|
from app.services.standards import StandardsService
|
|
|
|
# Create services
|
|
standards_service = StandardsService()
|
|
|
|
# Create router
|
|
router = APIRouter(prefix="/standards", tags=["standards"])
|
|
|
|
@router.get("/", response_model=List[Standard])
|
|
async def get_all_standards():
|
|
"""
|
|
Get all available compliance standards.
|
|
|
|
Returns:
|
|
List of all standards
|
|
"""
|
|
try:
|
|
standards = await standards_service.get_all_standards()
|
|
return standards
|
|
except Exception as e:
|
|
logger.error(f"Error retrieving standards: {str(e)}")
|
|
raise HTTPException(status_code=500, detail=f"Error retrieving standards: {str(e)}")
|
|
|
|
@router.get("/{standard_id}", response_model=Standard)
|
|
async def get_standard(standard_id: str):
|
|
"""
|
|
Get a specific standard by ID.
|
|
|
|
Args:
|
|
standard_id: The standard ID
|
|
|
|
Returns:
|
|
Standard details
|
|
"""
|
|
try:
|
|
standard = await standards_service.get_standard(standard_id)
|
|
if not standard:
|
|
raise HTTPException(status_code=404, detail=f"Standard with ID {standard_id} not found")
|
|
return standard
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error retrieving standard: {str(e)}")
|
|
raise HTTPException(status_code=500, detail=f"Error retrieving standard: {str(e)}")
|
|
|
|
@router.post("/upload", response_model=StandardUploadResponse)
|
|
async def upload_standard(file: UploadFile = File(...)):
|
|
"""
|
|
Upload a new compliance standard definition.
|
|
|
|
Args:
|
|
file: JSON file containing standard definition
|
|
|
|
Returns:
|
|
StandardUploadResponse with standard ID
|
|
"""
|
|
try:
|
|
# Check file extension
|
|
if not file.filename:
|
|
raise HTTPException(status_code=400, detail="Filename is required")
|
|
|
|
if not file.filename.lower().endswith('.json'):
|
|
raise HTTPException(status_code=400, detail="Standard definition must be a JSON file")
|
|
|
|
# Log the standards service instance ID to verify singleton pattern
|
|
logger.info(f"Standards API - Using StandardsService instance: {id(standards_service)}")
|
|
logger.info(f"Standards API - Standards count before upload: {len(standards_service.standards)}")
|
|
|
|
# Process standard
|
|
standard = await standards_service.upload_standard(file.file, file.filename)
|
|
|
|
# Log the updated standards count
|
|
logger.info(f"Standards API - Standards count after upload: {len(standards_service.standards)}")
|
|
logger.info(f"Standards API - Uploaded standard: {standard.name} (ID: {standard.id})")
|
|
|
|
return StandardUploadResponse(
|
|
standard_id=standard.id,
|
|
name=standard.name,
|
|
requirement_count=len(standard.requirements),
|
|
message="Standard uploaded successfully."
|
|
)
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=400, detail=str(e))
|
|
except Exception as e:
|
|
logger.error(f"Error processing standard: {str(e)}")
|
|
raise HTTPException(status_code=500, detail=f"Error processing standard: {str(e)}")
|
|
|
|
@router.get("/search/", response_model=List[Standard])
|
|
async def search_standards(name: Optional[str] = Query(None, description="Standard name to search for")):
|
|
"""
|
|
Search for standards by name.
|
|
|
|
Args:
|
|
name: Standard name to search for (optional)
|
|
|
|
Returns:
|
|
List of matching standards
|
|
"""
|
|
try:
|
|
if name:
|
|
standard = await standards_service.get_standard_by_name(name)
|
|
return [standard] if standard else []
|
|
else:
|
|
return await standards_service.get_all_standards()
|
|
except Exception as e:
|
|
logger.error(f"Error searching standards: {str(e)}")
|
|
raise HTTPException(status_code=500, detail=f"Error searching standards: {str(e)}")
|