Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build": "bun node_modules/@typescript/native/bin/tsc --noEmit && bun scripts/build.ts",
"db:preflight": "bun dist/databasePreflight.js",
"deploy:prepare": "bun run build && bun run db:preflight",
"auth:reset-password": "NODE_ENV=production doppler run --config prd --project rajohan -- bun dist/resetDashboardPassword.js",
"auth:reset-password": "MIRA_DASHBOARD_DB_PATH=${MIRA_DASHBOARD_DB_PATH:-/home/ubuntu/projects/mira-dashboard-state/mira-dashboard.db} NODE_ENV=production doppler run --config prd --project rajohan --preserve-env=MIRA_DASHBOARD_DB_PATH -- bun dist/resetDashboardPassword.js",
"start": "NODE_ENV=production doppler run --config prd --project rajohan -- bun dist/serverStart.js",
"start:worker": "NODE_ENV=production doppler run --config prd --project rajohan -- bun dist/workerStart.js",
"dev": "MIRA_DASHBOARD_DISABLE_SCHEDULER=1 doppler run --config prd --project rajohan -- bun --watch src/serverStart.ts",
Expand Down
13 changes: 13 additions & 0 deletions backend/src/lib/safePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ function isFilesystemRoot(rootPath: string): boolean {
return path.parse(rootPath).root === rootPath;
}

/** Resolves an absolute path while rejecting empty, null-byte, relative, and root paths. */
export function resolveAbsoluteNonRootPath(value: string, label: string): string {
const trimmed = value.trim();
if (!trimmed || trimmed.includes("\0") || !path.isAbsolute(trimmed)) {
throw new TypeError(`${label} must be an absolute non-root path`);
}
const resolved = path.resolve(trimmed);
if (isFilesystemRoot(resolved)) {
throw new TypeError(`${label} must be an absolute non-root path`);
}
return resolved;
}

function isWithinCanonicalRoot(candidate: string, root: string, normalizedRoot: string) {
return candidate === root || candidate.startsWith(normalizedRoot);
}
Expand Down
10 changes: 10 additions & 0 deletions backend/src/lib/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ export function nonEmptyEnvironmentFallback(name: string, fallback: string): str
return value && value.length > 0 ? value : fallback;
}

/** Returns the validated effective Dashboard listen port. */
export function resolveDashboardPort(value = process.env.PORT): number {
const trimmed = value?.trim() ?? "";
if (!/^\d+$/u.test(trimmed)) {
return 3100;
}
const port = Number(trimmed);
return port > 0 && port <= 65_535 ? port : 3100;
}

/** Converts optional values to strings while preserving empty/undefined fallback behavior. */
export function stringFallback(value?: unknown, fallback = ""): string {
return String(value ?? fallback);
Expand Down
Loading