fix: show external drives in directory browser on Linux
- Add mount point detection for /media, /mnt, /run/media - Display mount points as quick-access entries when browsing home dir - Allow navigation to mount points while maintaining security scope Fixes #2908
This commit is contained in:
parent
731f180e22
commit
4c9f9dac3c
1 changed files with 61 additions and 2 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
||||
import { resolve, dirname, join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { homedir, platform } from "node:os";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const dynamic = "force-dynamic";
|
||||
|
|
@ -24,6 +24,42 @@ function getDevRoot(): string {
|
|||
return homedir();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available mount points on Linux (external drives, removable media)
|
||||
* Returns paths like /media, /mnt, /run/media/<user>
|
||||
*/
|
||||
function getLinuxMountPoints(): string[] {
|
||||
const mountPoints: string[] = [];
|
||||
const home = homedir();
|
||||
|
||||
const standardMounts = ["/media", "/mnt", "/run/media"];
|
||||
|
||||
for (const mp of standardMounts) {
|
||||
if (existsSync(mp)) {
|
||||
mountPoints.push(mp);
|
||||
}
|
||||
}
|
||||
|
||||
const runMediaUser = `/run/media/${home.split("/").pop()}`;
|
||||
if (existsSync(runMediaUser)) {
|
||||
mountPoints.push(runMediaUser);
|
||||
}
|
||||
|
||||
return mountPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get additional root-level directories to show as shortcuts on Linux
|
||||
* (for accessing external drives and mounted filesystems)
|
||||
*/
|
||||
function getAdditionalRoots(): string[] {
|
||||
const os = platform();
|
||||
if (os === "linux") {
|
||||
return getLinuxMountPoints();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/browse-directories?path=/some/path
|
||||
*
|
||||
|
|
@ -46,8 +82,15 @@ export async function GET(request: Request): Promise<Response> {
|
|||
// if no devRoot is configured. Navigating to the parent of devRoot is
|
||||
// allowed (one level up) so the UI can show the devRoot in context,
|
||||
// but nothing further.
|
||||
// Also allow navigation to common mount points (/media, /mnt, /run/media) on Linux
|
||||
const devRootParent = dirname(devRoot);
|
||||
if (!targetPath.startsWith(devRoot) && targetPath !== devRootParent) {
|
||||
const additionalRoots = getAdditionalRoots();
|
||||
const isAllowedPath =
|
||||
targetPath.startsWith(devRoot) ||
|
||||
targetPath === devRootParent ||
|
||||
additionalRoots.some((root) => targetPath.startsWith(root));
|
||||
|
||||
if (!isAllowedPath) {
|
||||
return Response.json(
|
||||
{ error: "Path outside allowed scope" },
|
||||
{ status: 403 },
|
||||
|
|
@ -74,6 +117,9 @@ export async function GET(request: Request): Promise<Response> {
|
|||
const parentAllowed = parentPath.startsWith(devRootParent) && parentPath !== targetPath;
|
||||
const entries: Array<{ name: string; path: string }> = [];
|
||||
|
||||
// On Linux, show mount points as quick-access when browsing from home directory
|
||||
const showMountPoints = platform() === "linux" && (targetPath === homedir() || targetPath === devRoot);
|
||||
|
||||
try {
|
||||
const items = readdirSync(targetPath, { withFileTypes: true });
|
||||
for (const item of items) {
|
||||
|
|
@ -87,6 +133,19 @@ export async function GET(request: Request): Promise<Response> {
|
|||
path: resolve(targetPath, item.name),
|
||||
});
|
||||
}
|
||||
|
||||
// Add mount points as quick-access entries on Linux
|
||||
if (showMountPoints) {
|
||||
for (const mp of additionalRoots) {
|
||||
if (existsSync(mp)) {
|
||||
const mpName = mp.split("/").pop() || mp;
|
||||
entries.push({
|
||||
name: mpName,
|
||||
path: mp,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Permission denied or other read error — return empty entries
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue