""" API routes for script generation. """ import os import uuid from fastapi import APIRouter, Depends, HTTPException, Request, status from app.api.deps import get_devops_service, get_logger, get_settings from app.core.security import limiter from app.models.schemas import ConfigState, GeneratedFiles from app.services.script_validator import ScriptValidator from app.core.logging import logger as app_logger router = APIRouter() script_validator = ScriptValidator(app_logger) @router.post("/generate-script", response_model=GeneratedFiles) @limiter.limit("10/minute") async def generate_script( request: Request, config: ConfigState, service=Depends(get_devops_service), settings=Depends(get_settings), logger=Depends(get_logger), ): """Generate a VPS setup script based on configuration.""" client_ip = request.client.host if request.client else "unknown" logger.info(f"Script generation request from {client_ip} for {config.stackType}") try: # Generate unique filename script_id = str(uuid.uuid4())[:8] # Generate bash script script_content = service.generate_bash_script(config, script_id) script_filename = f"setup-{script_id}.sh" script_path = settings.generated_dir / script_filename # Ensure generated directory exists script_path.parent.mkdir(exist_ok=True) # Write script file with open(script_path, "w") as f: f.write(script_content) # Make script executable os.chmod(script_path, 0o755) # Create script URL for frontend script_url = f"/download/{script_filename}" response = GeneratedFiles( script_path=str(script_path), script_url=script_url, description="VPS Setup Script for " + config.stackType + " + " + config.webServer + " + " + (config.database or "No Database"), ) # Generate nginx config if web server is selected if config.webServer and config.webServer != "none": nginx_config = service.generate_nginx_config(config, script_id) nginx_filename = f"nginx-{script_id}.conf" nginx_path = settings.generated_dir / nginx_filename with open(nginx_path, "w") as f: f.write(nginx_config) response.nginx_config_path = str(nginx_path) response.nginx_url = f"/download/{nginx_filename}" return response except Exception as e: logger.error(f"Failed to generate script: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate script: {str(e)}", ) @router.get("/validate-script/{file_id}") @limiter.limit("20/minute") async def validate_script( request: Request, file_id: str, logger=Depends(get_logger), settings=Depends(get_settings), ): """ Validate a generated bash script for syntax and best practices """ client_ip = request.client.host if request.client else "unknown" logger.info(f"Script validation request from {client_ip} for file {file_id}") try: # Find the script file script_path = settings.generated_dir / f"setup-{file_id}.sh" if not script_path.exists(): raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Script not found: {file_id}" ) # Read script content with open(script_path, 'r') as f: script_content = f.read() # Validate validation_result = script_validator.validate_bash_script(script_content) logger.info(f"Validation result for {file_id}: valid={validation_result['valid']}, score={validation_result['score']}") return validation_result except HTTPException: raise except Exception as e: logger.error(f"Failed to validate script: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to validate script: {str(e)}" ) @router.get("/validate-nginx/{file_id}") @limiter.limit("20/minute") async def validate_nginx( request: Request, file_id: str, logger=Depends(get_logger), settings=Depends(get_settings), ): """ Validate a generated nginx configuration for syntax and best practices """ client_ip = request.client.host if request.client else "unknown" logger.info(f"Nginx validation request from {client_ip} for file {file_id}") try: # Find the nginx config file nginx_path = settings.generated_dir / f"nginx-{file_id}.conf" if not nginx_path.exists(): raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Nginx config not found: {file_id}" ) # Read nginx content with open(nginx_path, 'r') as f: nginx_content = f.read() # Validate validation_result = script_validator.validate_nginx_config(nginx_content) logger.info(f"Validation result for {file_id}: valid={validation_result['valid']}, score={validation_result['score']}") return validation_result except HTTPException: raise except Exception as e: logger.error(f"Failed to validate nginx config: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to validate nginx config: {str(e)}" )