From fdd1d21bc7ef7c33d6dd49d662309fb6fdba1a9a Mon Sep 17 00:00:00 2001 From: Developer Date: Tue, 2 Jun 2026 19:57:53 +0000 Subject: [PATCH] refactor: fix user.id references and add missing docker imports (Task 3.4 prep) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix user_id → user.id in tool_instances.py (4 occurrences) - Add get_container_status and get_container_logs imports Refs: repo-restructure Task 3.4 --- apps/api/src/api/config_folders.py | 101 ++------------------------ apps/api/src/api/tool_instances.py | 10 ++- apps/api/src/schemas/config_folder.py | 2 + 3 files changed, 14 insertions(+), 99 deletions(-) diff --git a/apps/api/src/api/config_folders.py b/apps/api/src/api/config_folders.py index 559a65d..631bde1 100644 --- a/apps/api/src/api/config_folders.py +++ b/apps/api/src/api/config_folders.py @@ -4,111 +4,22 @@ import logging import uuid from fastapi import APIRouter, Depends, HTTPException, status -from pydantic import BaseModel, Field, field_validator from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session from src.models.config_folder import ConfigFolder +from src.schemas.config_folder import ( + ConfigFolderCreate, + ConfigFolderUpdate, + ConfigFolderResponse, + ProjectOverrideCreate, +) logger = logging.getLogger(__name__) router = APIRouter(prefix="/config-folders", tags=["config-folders"]) -MAX_FOLDER_SIZE_MB = 10 -MAX_FOLDER_SIZE_BYTES = MAX_FOLDER_SIZE_MB * 1024 * 1024 - - -class ConfigFolderCreate(BaseModel): - name: str = Field(description="Folder name (unique per user)") - description: str | None = Field(default=None, description="Optional description") - mount_path: str = Field(description="Default mount path in container") - files: dict = Field(default_factory=dict, description="Files as {path: content}") - - @field_validator("mount_path") - @classmethod - def validate_mount_path(cls, v: str) -> str: - if not v.startswith("/"): - raise ValueError("Mount path must be absolute (start with /)") - return v - - @field_validator("files") - @classmethod - def validate_files(cls, v: dict) -> dict: - total_size = 0 - for path, content in v.items(): - # Check for path traversal - if ".." in path or path.startswith("/"): - raise ValueError(f"Invalid file path: {path}") - total_size += len(content.encode("utf-8")) - - if total_size > MAX_FOLDER_SIZE_BYTES: - raise ValueError(f"Total folder size exceeds {MAX_FOLDER_SIZE_MB}MB limit") - - return v - - -class ConfigFolderUpdate(BaseModel): - name: str | None = Field(default=None, description="Folder name") - description: str | None = Field(default=None, description="Optional description") - mount_path: str | None = Field(default=None, description="Default mount path") - files: dict | None = Field(default=None, description="Files as {path: content}") - is_active: bool | None = Field(default=None, description="Active/inactive toggle") - - @field_validator("mount_path") - @classmethod - def validate_mount_path(cls, v: str | None) -> str | None: - if v is None: - return v - if not v.startswith("/"): - raise ValueError("Mount path must be absolute (start with /)") - return v - - @field_validator("files") - @classmethod - def validate_files(cls, v: dict | None) -> dict | None: - if v is None: - return v - - total_size = 0 - for path, content in v.items(): - # Check for path traversal - if ".." in path or path.startswith("/"): - raise ValueError(f"Invalid file path: {path}") - total_size += len(content.encode("utf-8")) - - if total_size > MAX_FOLDER_SIZE_BYTES: - raise ValueError(f"Total folder size exceeds {MAX_FOLDER_SIZE_MB}MB limit") - - return v - - -class ProjectOverrideCreate(BaseModel): - mount_path: str | None = Field(default=None, description="Override mount path") - files: dict = Field(default_factory=dict, description="Override files") - - @field_validator("mount_path") - @classmethod - def validate_mount_path(cls, v: str | None) -> str | None: - if v is None: - return v - if not v.startswith("/"): - raise ValueError("Mount path must be absolute (start with /)") - return v - - -class ConfigFolderResponse(BaseModel): - id: str - user_id: str - name: str - description: str | None - mount_path: str - files: dict - project_overrides: dict | None - is_active: bool - created_at: str - updated_at: str - @router.get("", summary="List config folders", description="Get all config folders for the current user.") async def list_config_folders( diff --git a/apps/api/src/api/tool_instances.py b/apps/api/src/api/tool_instances.py index e5b8742..5200342 100644 --- a/apps/api/src/api/tool_instances.py +++ b/apps/api/src/api/tool_instances.py @@ -33,7 +33,9 @@ from src.services.docker import ( execute_compose_command, find_free_port, get_container_id, + get_container_logs, get_container_name, + get_container_status, recreate_tunnel, render_compose_template, start_cloudflared_tunnel, @@ -266,7 +268,7 @@ async def create_instance( status_code=status.HTTP_404_NOT_FOUND, detail="config profile not found", ) - if config_profile.user_id != user_id: + if config_profile.user_id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="config profile does not belong to user", @@ -577,7 +579,7 @@ async def start_instance( status_code=status.HTTP_404_NOT_FOUND, detail="config profile not found", ) - if selected_profile.user_id != user_id: + if selected_profile.user_id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="config profile does not belong to user", @@ -912,7 +914,7 @@ async def restart_instance( status_code=status.HTTP_404_NOT_FOUND, detail="config profile not found", ) - if stored_profile.user_id != user_id: + if stored_profile.user_id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="config profile does not belong to user", @@ -1297,7 +1299,7 @@ async def proxy_to_instance( ) # Verify ownership - if instance.owner_id != user_id: + if instance.owner_id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="not authorized to access this instance", diff --git a/apps/api/src/schemas/config_folder.py b/apps/api/src/schemas/config_folder.py index 49bab31..51d6af5 100644 --- a/apps/api/src/schemas/config_folder.py +++ b/apps/api/src/schemas/config_folder.py @@ -1,5 +1,7 @@ """Config folder request/response schemas.""" +import uuid + from pydantic import BaseModel, Field