| import path from "path"; |
| import fs from "fs/promises"; |
| import { existsSync, mkdirSync } from "fs"; |
|
|
| import { ENV_CONFIG } from "../env-config"; |
|
|
| function resolveWorkspaceBase(): string { |
| |
| const workspaceRoot = ENV_CONFIG.WORKSPACE_ROOT; |
| |
| try { |
| if (!existsSync(workspaceRoot)) { |
| mkdirSync(workspaceRoot, { recursive: true }); |
| } |
| return workspaceRoot; |
| } catch (e) { |
| console.error(`[SYSTEM] Critical Storage Error for ${workspaceRoot}:`, e); |
| return workspaceRoot; |
| } |
| } |
|
|
| const WORKSPACE_BASE = resolveWorkspaceBase(); |
|
|
| |
| |
| |
| |
| export async function getUserWorkspaceRoot(userId: string): Promise<string> { |
| const userRoot = path.join( WORKSPACE_BASE, userId); |
| try { |
| await fs.mkdir(userRoot, { recursive: true }); |
| } catch (e: unknown) { |
| if (e && typeof e === 'object' && 'code' in e && e.code === "EACCES") { |
| throw new Error(`Permission Denied: Cannot create ${userRoot}. Ensure your persistent storage is mounted with write access for UID 1000.`); |
| } |
| throw e; |
| } |
| return userRoot; |
| } |
|
|
| |
| |
| |
| |
| export async function resolveSafeProjectPath(userId: string, projectName: string, subPath: string = ""): Promise<string> { |
| const userRoot = await getUserWorkspaceRoot(userId); |
| const projectRoot = path.resolve( userRoot, projectName.replace(/[^a-zA-Z0-9-_]/g, "-").slice(0, 60)); |
| |
| |
| const targetPath = path.resolve( projectRoot, subPath); |
|
|
| |
| if (!targetPath.startsWith(projectRoot)) { |
| throw new Error("Security Violation: Path traversal detected."); |
| } |
|
|
| return targetPath; |
| } |
|
|
| |
| |
| |
| export async function resolveSafePath(userId: string, subPath: string): Promise<string> { |
| const userRoot = await getUserWorkspaceRoot(userId); |
| |
| |
| const targetPath = path.resolve( userRoot, subPath); |
|
|
| |
| if (!targetPath.startsWith(userRoot)) { |
| throw new Error("Security Violation: Path traversal detected."); |
| } |
|
|
| return targetPath; |
| } |
|
|