From 85ff2fd17ab974812df3240d2c6a528ac1c01222 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Tue, 10 Mar 2026 19:04:49 +0800 Subject: [PATCH] v0.1.4 --- backend/main.py | 13 ++++++++++++- frontend/docker/nginx.conf | 12 ++++++++++++ .../src/modules/dashboard/BotDashboardModule.tsx | 9 ++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/backend/main.py b/backend/main.py index 704cac0..d350237 100644 --- a/backend/main.py +++ b/backend/main.py @@ -352,12 +352,23 @@ def _is_panel_protected_api_path(path: str) -> bool: "/api/health/cache", }: return False - # Bot-scoped APIs are protected by the bot's own access password only. + if _is_bot_panel_management_api_path(raw): + return True + # Bot-scoped content/chat APIs are protected by the bot's own access password only. if _extract_bot_id_from_api_path(raw): return False return True +def _is_bot_panel_management_api_path(path: str) -> bool: + raw = str(path or "").strip() + if not raw.startswith("/api/bots/"): + return False + if not _extract_bot_id_from_api_path(raw): + return False + return raw.endswith("/start") or raw.endswith("/stop") or raw.endswith("/deactivate") or raw == f"/api/bots/{_extract_bot_id_from_api_path(raw)}" + + @app.middleware("http") async def bot_access_password_guard(request: Request, call_next): if request.method.upper() == "OPTIONS": diff --git a/frontend/docker/nginx.conf b/frontend/docker/nginx.conf index 535cfac..2a2321d 100644 --- a/frontend/docker/nginx.conf +++ b/frontend/docker/nginx.conf @@ -22,6 +22,18 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } + location /public/ { + proxy_pass http://nanobot_backend/public/; + proxy_http_version 1.1; + proxy_request_buffering off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + location /ws/monitor/ { proxy_pass http://nanobot_backend/ws/monitor/; proxy_http_version 1.1; diff --git a/frontend/src/modules/dashboard/BotDashboardModule.tsx b/frontend/src/modules/dashboard/BotDashboardModule.tsx index f86d90f..d4edfae 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.tsx +++ b/frontend/src/modules/dashboard/BotDashboardModule.tsx @@ -376,6 +376,8 @@ function workspaceFileAction(path: string): 'preview' | 'download' | 'unsupporte const WORKSPACE_LINK_PREFIX = 'https://workspace.local/open/'; const WORKSPACE_ABS_PATH_PATTERN = /\/root\/\.nanobot\/workspace\/[^\s<>"'`)\],,。!?;:]+/gi; +const WORKSPACE_RELATIVE_PATH_PATTERN = + /(^|[\s(\[])(\/[^\s<>"'`)\]]+\.(?:md|markdown|json|txt|log|csv|tsv|yaml|yml|toml|html|htm|pdf|png|jpg|jpeg|gif|webp|svg))(?![A-Za-z0-9_./-])/gim; function buildWorkspaceLink(path: string) { return `${WORKSPACE_LINK_PREFIX}${encodeURIComponent(path)}`; @@ -403,11 +405,16 @@ function decorateWorkspacePathsForMarkdown(text: string) { return `[${markdownPath}](${buildWorkspaceLink(normalized)})`; }, ); - return normalizedExistingLinks.replace(WORKSPACE_ABS_PATH_PATTERN, (fullPath) => { + const withAbsoluteLinks = normalizedExistingLinks.replace(WORKSPACE_ABS_PATH_PATTERN, (fullPath) => { const normalized = normalizeDashboardAttachmentPath(fullPath); if (!normalized) return fullPath; return `[${fullPath}](${buildWorkspaceLink(normalized)})`; }); + return withAbsoluteLinks.replace(WORKSPACE_RELATIVE_PATH_PATTERN, (full, prefix: string, rawPath: string) => { + const normalized = normalizeDashboardAttachmentPath(rawPath); + if (!normalized) return full; + return `${prefix}[${rawPath}](${buildWorkspaceLink(normalized)})`; + }); } function normalizeAttachmentPaths(raw: unknown): string[] {