Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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