Refine remote config and path browsing

This commit is contained in:
Dymas
2026-05-26 10:50:31 +02:00
parent 83497d8ff0
commit 4c430e1982
4 changed files with 96 additions and 4 deletions
+47
View File
@@ -2689,6 +2689,8 @@ class HandlerRouteTests(unittest.TestCase):
self.assertEqual(handler.json_status, HTTPStatus.OK)
self.assertEqual(handler.json_payload["path"], allowed_root)
self.assertEqual(handler.json_payload["home_path"], allowed_root)
self.assertEqual(handler.json_payload["root_paths"][0], allowed_root)
self.assertIn(allowed_root, handler.json_payload["root_paths"])
def test_remote_path_roots_include_explicit_allowlist(self):
with tempfile.TemporaryDirectory() as base_root, tempfile.TemporaryDirectory() as extra_root:
@@ -2705,6 +2707,31 @@ class HandlerRouteTests(unittest.TestCase):
self.assertIn(Path(base_root).resolve(), roots)
self.assertIn(Path(extra_root).resolve(), roots)
def test_remote_filesystem_browse_returns_all_allowed_root_paths(self):
with tempfile.TemporaryDirectory() as base_root, tempfile.TemporaryDirectory() as extra_root:
APP.save_runtime_config({"download_dir": base_root, "mode": "sub", "quality": "best"})
encoded = base64.b64encode(b"demo:secret-pass").decode("ascii")
handler = DummyHandler("/api/fs/browse?path=&mode=dir")
handler.client_address = ("192.168.1.25", 8421)
handler.headers["Authorization"] = f"Basic {encoded}"
with mock.patch.dict(
os.environ,
{
"ANI_CLI_WEB_ALLOW_REMOTE": "1",
"ANI_CLI_WEB_AUTH_USERNAME": "demo",
"ANI_CLI_WEB_AUTH_PASSWORD": "secret-pass",
"ANI_CLI_WEB_REMOTE_PATH_ROOTS": extra_root,
},
clear=False,
):
APP.Handler.do_GET(handler)
self.assertEqual(handler.json_status, HTTPStatus.OK)
self.assertEqual(handler.json_payload["root_paths"][:2], [extra_root, base_root])
self.assertIn(extra_root, handler.json_payload["root_paths"])
self.assertIn(base_root, handler.json_payload["root_paths"])
def test_config_post_accepts_discord_webhook_fields(self):
body = b'{"download_dir":"/tmp/example","mode":"sub","quality":"best","discord_webhook_url":"https://discord.com/api/webhooks/123456/test-token","discord_webhook_events":["runtime_error","watchlist_refresh_failed","bad"]}'
handler = DummyHandler("/api/config", body=body, content_length=len(body))
@@ -2723,6 +2750,25 @@ class HandlerRouteTests(unittest.TestCase):
self.assertEqual(handler.error_status, HTTPStatus.BAD_REQUEST)
self.assertIn("official discord webhook host", handler.error_message.lower())
def test_config_post_partial_update_preserves_existing_paths(self):
with tempfile.TemporaryDirectory() as existing_root:
APP.save_runtime_config(
{
"download_dir": existing_root,
"mode": "sub",
"quality": "best",
"jellyfin_tv_dir": existing_root,
}
)
body = b'{"mode":"dub"}'
handler = DummyHandler("/api/config", body=body, content_length=len(body))
APP.Handler.do_POST(handler)
self.assertEqual(handler.json_status, HTTPStatus.OK)
self.assertEqual(handler.json_payload["download_dir"], existing_root)
self.assertEqual(handler.json_payload["jellyfin_tv_dir"], existing_root)
self.assertEqual(handler.json_payload["mode"], "dub")
def test_remote_config_post_rejects_download_dir_outside_allowed_roots(self):
with tempfile.TemporaryDirectory() as allowed_root, tempfile.TemporaryDirectory() as blocked_root:
APP.save_runtime_config({"download_dir": allowed_root, "mode": "sub", "quality": "best"})
@@ -3058,6 +3104,7 @@ class TemplateHelperTests(unittest.TestCase):
self.assertIn('class="ghost browse-path-btn"', APP.CONFIG_HTML)
self.assertIn('id="pathBrowserOverlay"', APP.CONFIG_HTML)
self.assertIn('/api/fs/browse?path=${encodeURIComponent(path || state.pathBrowser.path || "")}', APP.CONFIG_HTML)
self.assertIn('rootGroup.className = "browser-roots";', APP.CONFIG_HTML)
def test_search_page_sends_watchlist_auto_download_series(self):
self.assertIn('auto_download_series: $("seasonInput").value || "1"', APP.INDEX_HTML)