from pathlib import Path from tempfile import TemporaryDirectory import pytest from app.models.project import ProjectManager def test_project_paths_reject_traversal_and_absolute_components(): with TemporaryDirectory() as temp_dir: original = ProjectManager.PROJECTS_DIR ProjectManager.PROJECTS_DIR = temp_dir try: with pytest.raises(ValueError, match="invalid_project_id"): ProjectManager._get_project_dir("../escape") with pytest.raises(ValueError, match="invalid_project_id"): ProjectManager._get_project_dir("/tmp/escape") assert ProjectManager.get_project("../escape") is None finally: ProjectManager.PROJECTS_DIR = original def test_project_metadata_write_leaves_no_partial_temp_file(): with TemporaryDirectory() as temp_dir: original = ProjectManager.PROJECTS_DIR ProjectManager.PROJECTS_DIR = temp_dir try: project = ProjectManager.create_project("atomic") assert ProjectManager.get_project(project.project_id) is not None project_files = {path.name for path in Path(temp_dir, project.project_id).iterdir()} assert project_files == {"project.json", "files"} finally: ProjectManager.PROJECTS_DIR = original