diff --git a/CHANGELOG.md b/CHANGELOG.md index 5238a0d..1377cd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +### Changed + +- Other plugins' top-bar buttons (rgthree-comfy, Crystools...) are hidden without the *Manager* permission, like ComfyUI Manager's. Their settings kept on the server, which apply to everyone, need *Manager* too +- Pixaroma's Workflows panel is hidden along with ComfyUI's Workflows and Apps tabs (admin setting now called *Hide other workflow browsers*), and its shortcut opens Files. Its server routes are refused to everyone but admins: they read the workflows folder straight from disk, private folders included + ## 1.2.3 (2026-09-27) ### Fixed diff --git a/docs/accounts.md b/docs/accounts.md index 196e544..2ad8812 100644 --- a/docs/accounts.md +++ b/docs/accounts.md @@ -7,7 +7,7 @@ | *(none)*, a viewer | Watch shared workflows, chat, follow people, open snapshots as private copies | | **Edit** | Change shared workflows, save or rename workflow files, take and restore snapshots, upload files | | **Queue** | Queue prompts, stop or remove your own runs, free memory. Stopping or removing someone else's, or clearing the queue, needs *Admin* | -| **Manager** | Open ComfyUI Manager: install, update or remove custom nodes and models, snapshots, restart | +| **Manager** | Open ComfyUI Manager: install, update or remove custom nodes and models, snapshots, restart. Also other plugins' top-bar buttons and their server-wide settings (rgthree-comfy, Crystools) | | **Admin** | Everything, plus deleting workflow files, accounts and server settings | Queueing, uploads, and saving or deleting workflow files are checked by the server too, when *Enforce permissions on the ComfyUI API* is on (the default). A viewer cannot get around it with a script. diff --git a/docs/settings.md b/docs/settings.md index 8ea42b3..ff3a4f8 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -27,7 +27,7 @@ Admins change these under **Admin → Server settings**. They are stored in `rig | `guest_permissions` | `{"edit": false, "queue": false}` | What guests may do | | `broadcast_execution` | `true` | Send progress and previews to everyone, not only whoever queued | | `hide_comfy_account` | `false` | Hide ComfyUI's Comfy.org sign-in button and dialog | -| `hide_comfy_file_tabs` | `true` | Hide ComfyUI's own Workflows and Apps sidebar tabs; RigShare's Files tab replaces them and their shortcuts open it | +| `hide_comfy_file_tabs` | `true` | Hide other workflow browsers: ComfyUI's Workflows and Apps sidebar tabs and Pixaroma's Workflows panel. RigShare's Files tab replaces them and their shortcuts open it | | `hide_api_templates` | `false` | Remove templates that need paid API nodes from the template browser | | `api_protection.enabled` | `true` | Server-side checks on queue, interrupt, free and upload calls | | `api_protection.trusted_ips` | `["127.0.0.1", "::1"]` | Addresses or networks that skip login and checks | diff --git a/rigshare_core/routes.py b/rigshare_core/routes.py index 0acbdac..593edf1 100644 --- a/rigshare_core/routes.py +++ b/rigshare_core/routes.py @@ -33,6 +33,17 @@ LOGIN_WATCH = """""" +# Other plugins' server routes RigShare guards: (method or None, path prefix, +# permission, why). Settings they keep on the server apply to everyone, like +# ComfyUI Manager, so they need the same "manager" permission; Pixaroma's workflow +# browser reads the workflows folder straight from disk, private folders included. +PLUGIN_RULES = [ + ("POST", "/rgthree/api/", "manager", "changing rgthree-comfy's settings needs the 'manager' permission"), + ("POST", "/crystools/", "manager", "changing Crystools' settings needs the 'manager' permission"), + (None, "/pixaroma/api/workflows", "admin", + "Pixaroma's workflow browser shows every folder, private ones included; use RigShare's Files tab"), +] + # (method, path) prefixes that need a permission when api_protection is on. PROTECTED = [ ("POST", "/prompt", "queue"), @@ -798,6 +809,11 @@ def setup(server, store, hub): "details": "", "extra_info": {}}, "node_errors": {}}, status=403) break + for method, prefix, need, why in PLUGIN_RULES: + if (method is None or request.method == method) and api_path(request).startswith(prefix): + if not trusted(request.remote or "") and not perms_for(request).get(need) and not perms_for(request).get("admin"): + return web.json_response({"error": f"RigShare: {why}"}, status=403) + break refusal = await check_queue_ownership(request) if refusal: return web.json_response({"error": f"RigShare: {refusal}"}, status=403) diff --git a/tests/python/test_server.py b/tests/python/test_server.py index 80fbd6c..9770647 100644 --- a/tests/python/test_server.py +++ b/tests/python/test_server.py @@ -546,3 +546,36 @@ def test_file_changes_reach_who_can_see_them(run): assert await changed(b), "moves" await a.close(); await b.close() run(scenario()) + + +def test_other_plugins_server_routes(run): + async def scenario(): + async def ok(request): + from aiohttp import web + return web.json_response({"ok": True}) + + def routes(app): + for path in ("/rgthree/api/config", "/crystools/monitor/switch", "/pixaroma/api/workflows/index", + "/pixaroma/api/workflows/folder", "/pixaroma/api/fonts/list"): + app.router.add_route("*", path, ok) + + async with rig_server(setup=routes) as rig: + admin = await rig.setup_admin() + alice = await rig.add_user("alice", edit=True, queue=True) + manager = await rig.add_user("mgr", manager=True) + h = rig.http + + async def status(method, path, who): + return (await h.request(method, rig.url(path), headers=who)).status + + # Server-wide plugin settings: like ComfyUI Manager. + assert await status("POST", "/rgthree/api/config", alice) == 403 + assert await status("POST", "/crystools/monitor/switch", alice) == 403 + assert await status("POST", "/rgthree/api/config", manager) == 200 + assert await status("GET", "/rgthree/api/config", alice) == 200, "reading is fine" + # Pixaroma's workflow browser reads every folder from disk: admins only. + assert await status("GET", "/pixaroma/api/workflows/index", alice) == 403 + assert await status("POST", "/pixaroma/api/workflows/folder", manager) == 403 + assert await status("GET", "/pixaroma/api/workflows/index", admin) == 200 + assert await status("GET", "/pixaroma/api/fonts/list", alice) == 200, "the rest of Pixaroma works" + run(scenario()) diff --git a/web/rigshare/main.js b/web/rigshare/main.js index 71b27b1..088f7da 100644 --- a/web/rigshare/main.js +++ b/web/rigshare/main.js @@ -89,6 +89,19 @@ function installManagerGuard(client) { client.on("self", apply); client.on("status", apply); setTimeout(apply, 2000); // Manager registers its commands during setup + // Other plugins put their buttons in the same place as ComfyUI Manager (just + // before ComfyUI's settings group in the top bar): tag them so they are hidden + // the same way without the "manager" permission. Their server-side settings + // are guarded too (PLUGIN_RULES on the server). + const tagPluginButtons = () => { + const settings = app.menu?.settingsGroup?.element; + const bar = settings?.parentElement; + if (!bar) return; + for (const group of bar.children) { + if (group !== settings && group.classList.contains("comfyui-button-group")) group.classList.add("rs-plugin-bar"); + } + }; + setInterval(tagPluginButtons, 1000); } // Comfy.org account: hide the top-bar sign-in button and refuse the sign-in @@ -139,6 +152,15 @@ function installFileTabsGuard(client) { const apply = () => { if (!client.server) return; // wait for the server's settings const hide = hidden(); + document.body.classList.toggle("rs-hide-file-browsers", hide); + // Pixaroma's workflow browser lists every folder from disk, private ones + // included (the server refuses it to non-admins): its shortcut opens Files. + const pix = (manager()?.command?.commands ?? []).find((c) => c.id === "Pixaroma.OpenWorkflowBrowser"); + if (pix && !pix.__rigshare) { + const original = pix.function; + pix.function = (...args) => (hidden() ? openFiles() : original(...args)); + pix.__rigshare = true; + } for (const id of COMFY_FILE_TABS) { const tab = tabs().find((t) => t.id === id); // Open workflow tabs can be shown in the Workflows sidebar tab: keep it then. diff --git a/web/rigshare/panel.js b/web/rigshare/panel.js index 88439fa..02fdb27 100644 --- a/web/rigshare/panel.js +++ b/web/rigshare/panel.js @@ -866,7 +866,7 @@ export class RigSharePanel { line(f.broadcast, "Share execution progress", "Everyone sees progress and previews, not only whoever queued"), line(f.protect, "Enforce permissions on the ComfyUI API", "Blocks queueing, interrupting and uploads for users without permission"), line(f.hideAccount, "Hide the Comfy.org account login", "Removes ComfyUI's own sign-in button and dialog (used for paid API nodes)"), - line(f.hideFileTabs, "Hide ComfyUI's Workflows and Apps tabs", "RigShare's Files tab replaces them. Their shortcuts open Files instead"), + line(f.hideFileTabs, "Hide other workflow browsers", "ComfyUI's Workflows and Apps tabs, and Pixaroma's Workflows panel: RigShare's Files tab replaces them and their shortcuts open Files"), line(f.hideApiTemplates, "Hide API templates", "Removes templates that need paid API nodes from the template browser"), h("label", { class: "rs-label" }, "Trusted IPs / networks (skip login and checks)"), f.trusted, h("div", { class: "rs-row" }, h("label", { class: "rs-label rs-grow" }, "Auto snapshot every (min, 0 = off)"), f.interval), diff --git a/web/rigshare/styles.js b/web/rigshare/styles.js index 2590756..31288c1 100644 --- a/web/rigshare/styles.js +++ b/web/rigshare/styles.js @@ -107,6 +107,10 @@ code { font-family: ui-monospace, monospace; font-size: 11px; background: var(-- /* Comfy.org account sign-in hidden by the admin */ body.rs-hide-comfy-account [data-testid="login-button"], body.rs-hide-comfy-account [data-testid="login-button-popover"] { display: none !important; } +/* Other plugins' top-bar buttons (rgthree-comfy, Crystools...) hidden like ComfyUI Manager */ +body.rs-no-manager .rs-plugin-bar { display: none !important; } +/* Pixaroma's workflow browser button: RigShare's Files tab replaces it */ +body.rs-hide-file-browsers .pixwb-group-btn { display: none !important; } /* ComfyUI Manager hidden for accounts without the "manager" permission */ body.rs-no-manager .comfyui-button-group:has(> [title="ComfyUI Manager"]), body.rs-no-manager [title="ComfyUI Manager"],