From 405095a463cd4580d30bfb6d7cf547efdda65489 Mon Sep 17 00:00:00 2001 From: marko-kraemer Date: Fri, 9 May 2025 06:06:51 +0200 Subject: [PATCH] wip --- backend/sandbox/api.py | 138 +++++++++++++++------------------------- frontend/src/lib/api.ts | 82 ++++++++++++------------ 2 files changed, 92 insertions(+), 128 deletions(-) diff --git a/backend/sandbox/api.py b/backend/sandbox/api.py index d996eb5c..63fde35e 100644 --- a/backend/sandbox/api.py +++ b/backend/sandbox/api.py @@ -5,6 +5,7 @@ from fastapi import FastAPI, UploadFile, File, HTTPException, APIRouter, Form, D from fastapi.responses import Response from pydantic import BaseModel +from sandbox.sandbox import get_or_start_sandbox from utils.logger import logger from utils.auth_utils import get_optional_user_id from services.supabase import DBConnection @@ -90,12 +91,14 @@ async def get_sandbox_by_id_safely(client, sandbox_id: str): logger.error(f"No project found for sandbox ID: {sandbox_id}") raise HTTPException(status_code=404, detail="Sandbox not found - no project owns this sandbox ID") - project_id = project_result.data[0]['project_id'] - logger.debug(f"Found project {project_id} for sandbox {sandbox_id}") + # project_id = project_result.data[0]['project_id'] + # logger.debug(f"Found project {project_id} for sandbox {sandbox_id}") try: # Get the sandbox - sandbox = await get_or_create_project_sandbox(client, project_id) + sandbox = await get_or_start_sandbox(sandbox_id) + # Extract just the sandbox object from the tuple (sandbox, sandbox_id, sandbox_pass) + # sandbox = sandbox_tuple[0] return sandbox except Exception as e: @@ -133,46 +136,6 @@ async def create_file( logger.error(f"Error creating file in sandbox {sandbox_id}: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) -# For backward compatibility, keep the JSON version too -@router.post("/sandboxes/{sandbox_id}/files/json") -async def create_file_json( - sandbox_id: str, - file_request: dict, - request: Request = None, - user_id: Optional[str] = Depends(get_optional_user_id) -): - """Create a file in the sandbox using JSON (legacy support)""" - logger.info(f"Received JSON file creation request for sandbox {sandbox_id}, user_id: {user_id}") - client = await db.client - - # Verify the user has access to this sandbox - await verify_sandbox_access(client, sandbox_id, user_id) - - try: - # Get sandbox using the safer method - sandbox = await get_sandbox_by_id_safely(client, sandbox_id) - - # Get file path and content - path = file_request.get("path") - content = file_request.get("content", "") - - if not path: - logger.error(f"Missing file path in request for sandbox {sandbox_id}") - raise HTTPException(status_code=400, detail="File path is required") - - # Convert string content to bytes - if isinstance(content, str): - content = content.encode('utf-8') - - # Create file - sandbox.fs.upload_file(path, content) - logger.info(f"File created at {path} in sandbox {sandbox_id}") - - return {"status": "success", "created": True, "path": path} - except Exception as e: - logger.error(f"Error creating file in sandbox {sandbox_id}: {str(e)}") - raise HTTPException(status_code=500, detail=str(e)) - @router.get("/sandboxes/{sandbox_id}/files") async def list_files( sandbox_id: str, @@ -248,56 +211,57 @@ async def read_file( logger.error(f"Error reading file in sandbox {sandbox_id}: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) -@router.post("/project/{project_id}/sandbox/ensure-active") -async def ensure_project_sandbox_active( - project_id: str, - request: Request = None, - user_id: Optional[str] = Depends(get_optional_user_id) -): - """ - Ensure that a project's sandbox is active and running. - Checks the sandbox status and starts it if it's not running. - """ - logger.info(f"Received ensure sandbox active request for project {project_id}, user_id: {user_id}") - client = await db.client +# Should happen on server-side fully +# @router.post("/project/{project_id}/sandbox/ensure-active") +# async def ensure_project_sandbox_active( +# project_id: str, +# request: Request = None, +# user_id: Optional[str] = Depends(get_optional_user_id) +# ): +# """ +# Ensure that a project's sandbox is active and running. +# Checks the sandbox status and starts it if it's not running. +# """ +# logger.info(f"Received ensure sandbox active request for project {project_id}, user_id: {user_id}") +# client = await db.client - # Find the project and sandbox information - project_result = await client.table('projects').select('*').eq('project_id', project_id).execute() +# # Find the project and sandbox information +# project_result = await client.table('projects').select('*').eq('project_id', project_id).execute() - if not project_result.data or len(project_result.data) == 0: - logger.error(f"Project not found: {project_id}") - raise HTTPException(status_code=404, detail="Project not found") +# if not project_result.data or len(project_result.data) == 0: +# logger.error(f"Project not found: {project_id}") +# raise HTTPException(status_code=404, detail="Project not found") - project_data = project_result.data[0] +# project_data = project_result.data[0] - # For public projects, no authentication is needed - if not project_data.get('is_public'): - # For private projects, we must have a user_id - if not user_id: - logger.error(f"Authentication required for private project {project_id}") - raise HTTPException(status_code=401, detail="Authentication required for this resource") +# # For public projects, no authentication is needed +# if not project_data.get('is_public'): +# # For private projects, we must have a user_id +# if not user_id: +# logger.error(f"Authentication required for private project {project_id}") +# raise HTTPException(status_code=401, detail="Authentication required for this resource") - account_id = project_data.get('account_id') +# account_id = project_data.get('account_id') - # Verify account membership - if account_id: - account_user_result = await client.schema('basejump').from_('account_user').select('account_role').eq('user_id', user_id).eq('account_id', account_id).execute() - if not (account_user_result.data and len(account_user_result.data) > 0): - logger.error(f"User {user_id} not authorized to access project {project_id}") - raise HTTPException(status_code=403, detail="Not authorized to access this project") +# # Verify account membership +# if account_id: +# account_user_result = await client.schema('basejump').from_('account_user').select('account_role').eq('user_id', user_id).eq('account_id', account_id).execute() +# if not (account_user_result.data and len(account_user_result.data) > 0): +# logger.error(f"User {user_id} not authorized to access project {project_id}") +# raise HTTPException(status_code=403, detail="Not authorized to access this project") - try: - # Get or create the sandbox - logger.info(f"Ensuring sandbox is active for project {project_id}") - sandbox, sandbox_id, sandbox_pass = await get_or_create_project_sandbox(client, project_id) +# try: +# # Get or create the sandbox +# logger.info(f"Ensuring sandbox is active for project {project_id}") +# sandbox, sandbox_id, sandbox_pass = await get_or_create_project_sandbox(client, project_id) - logger.info(f"Successfully ensured sandbox {sandbox_id} is active for project {project_id}") +# logger.info(f"Successfully ensured sandbox {sandbox_id} is active for project {project_id}") - return { - "status": "success", - "sandbox_id": sandbox_id, - "message": "Sandbox is active" - } - except Exception as e: - logger.error(f"Error ensuring sandbox is active for project {project_id}: {str(e)}") - raise HTTPException(status_code=500, detail=str(e)) +# return { +# "status": "success", +# "sandbox_id": sandbox_id, +# "message": "Sandbox is active" +# } +# except Exception as e: +# logger.error(f"Error ensuring sandbox is active for project {project_id}: {str(e)}") +# raise HTTPException(status_code=500, detail=str(e)) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index d52e0b5c..25f8b652 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -183,52 +183,52 @@ export const getProject = async (projectId: string): Promise => { console.log('Raw project data from database:', data); - // If project has a sandbox, ensure it's started - if (data.sandbox?.id) { - // Fire off sandbox activation without blocking - const ensureSandboxActive = async () => { - try { - const { - data: { session }, - } = await supabase.auth.getSession(); + // // If project has a sandbox, ensure it's started + // if (data.sandbox?.id) { + // // Fire off sandbox activation without blocking + // const ensureSandboxActive = async () => { + // try { + // const { + // data: { session }, + // } = await supabase.auth.getSession(); - // For public projects, we don't need authentication - const headers: Record = { - 'Content-Type': 'application/json', - }; + // // For public projects, we don't need authentication + // const headers: Record = { + // 'Content-Type': 'application/json', + // }; - if (session?.access_token) { - headers['Authorization'] = `Bearer ${session.access_token}`; - } + // if (session?.access_token) { + // headers['Authorization'] = `Bearer ${session.access_token}`; + // } - console.log(`Ensuring sandbox is active for project ${projectId}...`); - const response = await fetch( - `${API_URL}/project/${projectId}/sandbox/ensure-active`, - { - method: 'POST', - headers, - }, - ); + // console.log(`Ensuring sandbox is active for project ${projectId}...`); + // const response = await fetch( + // `${API_URL}/project/${projectId}/sandbox/ensure-active`, + // { + // method: 'POST', + // headers, + // }, + // ); - if (!response.ok) { - const errorText = await response - .text() - .catch(() => 'No error details available'); - console.warn( - `Failed to ensure sandbox is active: ${response.status} ${response.statusText}`, - errorText, - ); - } else { - console.log('Sandbox activation successful'); - } - } catch (sandboxError) { - console.warn('Failed to ensure sandbox is active:', sandboxError); - } - }; + // if (!response.ok) { + // const errorText = await response + // .text() + // .catch(() => 'No error details available'); + // console.warn( + // `Failed to ensure sandbox is active: ${response.status} ${response.statusText}`, + // errorText, + // ); + // } else { + // console.log('Sandbox activation successful'); + // } + // } catch (sandboxError) { + // console.warn('Failed to ensure sandbox is active:', sandboxError); + // } + // }; - // Start the sandbox activation without awaiting - ensureSandboxActive(); - } + // // Start the sandbox activation without awaiting + // ensureSandboxActive(); + // } // Map database fields to our Project type const mappedProject: Project = {