From 99093adfbc9fe722a958b5b8a25eea855b63cfd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80?= <78488229+viktor138irk@users.noreply.github.com> Date: Mon, 11 May 2026 23:26:26 +0900 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20workspace=20file=20engine=20=D0=B4=D0=BB=D1=8F=20DevCo?= =?UTF-8?q?nsole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/file_workspace.py | 75 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 backend/file_workspace.py diff --git a/backend/file_workspace.py b/backend/file_workspace.py new file mode 100644 index 0000000..2d26839 --- /dev/null +++ b/backend/file_workspace.py @@ -0,0 +1,75 @@ +from pathlib import Path +import os + +DATA_DIR = Path(os.getenv('DEVCONSOLE_DATA_DIR', '/var/lib/devconsole')) +PROJECTS_DIR = DATA_DIR / 'projects' + + +class WorkspaceSecurityError(Exception): + pass + + +def ensure_workspace(path: str) -> Path: + workspace = Path(path).resolve() + + try: + workspace.relative_to(PROJECTS_DIR.resolve()) + except ValueError as exc: + raise WorkspaceSecurityError( + 'Workspace path is outside projects directory' + ) from exc + + return workspace + + +def build_tree(path: str, max_depth: int = 3): + workspace = ensure_workspace(path) + + def scan(directory: Path, depth: int = 0): + if depth > max_depth: + return [] + + result = [] + + for item in sorted(directory.iterdir(), key=lambda x: (x.is_file(), x.name.lower())): + if item.name.startswith('.'): + continue + + node = { + 'name': item.name, + 'path': item.as_posix(), + 'type': 'directory' if item.is_dir() else 'file', + } + + if item.is_dir(): + node['children'] = scan(item, depth + 1) + + result.append(node) + + return result + + return scan(workspace) + + +def read_file(path: str): + file_path = ensure_workspace(path) + + if file_path.is_dir(): + raise WorkspaceSecurityError('Cannot read directory') + + return file_path.read_text(encoding='utf-8', errors='ignore') + + +def save_file(path: str, content: str): + file_path = ensure_workspace(path) + + if file_path.is_dir(): + raise WorkspaceSecurityError('Cannot save directory') + + file_path.write_text(content, encoding='utf-8') + + return { + 'success': True, + 'path': file_path.as_posix(), + 'size': len(content), + }