summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/ui/app.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/ui/app.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/ui/app.py61
1 files changed, 51 insertions, 10 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/ui/app.py b/packages/meshbay-node/src/meshbay_node/ui/app.py
index 6fdc78f..fc6c04a 100644
--- a/packages/meshbay-node/src/meshbay_node/ui/app.py
+++ b/packages/meshbay-node/src/meshbay_node/ui/app.py
@@ -175,7 +175,7 @@ def create_ui_app(state: dict) -> FastAPI:
state,
(payload.get("name") or "").strip(),
(payload.get("shared_dir") or "").strip(),
- upload_dir=(payload.get("upload_dir") or "").strip(),
+ writable=bool(payload.get("writable", True)),
))
reload_fn = state.get("reload_fn")
if reload_fn:
@@ -349,13 +349,35 @@ def create_ui_app(state: dict) -> FastAPI:
(payload.get("path") or "").strip(),
name=(payload.get("name") or "").strip(),
kind=(payload.get("kind") or "generic").strip(),
- upload=bool(payload.get("upload", False)),
+ writable=bool(payload.get("writable",
+ payload.get("upload", False))),
+ removable=bool(payload.get("removable", False)),
))
reload_fn = state.get("reload_fn")
if reload_fn:
asyncio.ensure_future(reload_fn())
return result
+ @app.patch("/api/groups/{group_id}/roots/{root_name}")
+ async def update_root(group_id: str, root_name: str, payload: dict):
+ result = await _op(lambda: ops.update_root(
+ state, group_id, root_name,
+ writable=payload.get("writable"),
+ removable=payload.get("removable"),
+ ))
+ reload_fn = state.get("reload_fn")
+ if reload_fn:
+ asyncio.ensure_future(reload_fn())
+ return result
+
+ @app.put("/api/groups/{group_id}/roots/{root_name}/eject")
+ async def eject_root(group_id: str, root_name: str):
+ return await _op(lambda: ops.eject_root(state, group_id, root_name))
+
+ @app.put("/api/groups/{group_id}/roots/{root_name}/plug")
+ async def plug_root(group_id: str, root_name: str):
+ return await _op(lambda: ops.plug_root(state, group_id, root_name))
+
@app.delete("/api/groups/{group_id}/roots/{root_name}")
async def remove_root(group_id: str, root_name: str):
result = await _op(lambda: ops.remove_root(state, group_id, root_name))
@@ -397,14 +419,6 @@ def create_ui_app(state: dict) -> FastAPI:
"current_dir": progress.current_dir,
}
- # ── Upload toggle (operator only, localhost) ─────────────────────────
-
- @app.put("/api/groups/{group_id}/member-upload")
- async def set_member_upload(group_id: str, payload: dict):
- return await _op(lambda: ops.set_member_upload(
- state, group_id, bool(payload.get("allowed", False)),
- ))
-
# ── Enabled apps (operator only, localhost) ────────────────────────────
#
# Same loopback shape as member-upload: the Create Group wizard sets this
@@ -419,6 +433,33 @@ def create_ui_app(state: dict) -> FastAPI:
raise HTTPException(400, "apps must be a non-empty list")
return await _op(lambda: ops.set_enabled_apps(state, group_id, apps))
+ # ── App directories (operator only, localhost) ────────────────────────
+ #
+ # The loopback twin of the `app_directories` MNP op. One endpoint for every
+ # application, keyed by the app's own name, so adding one needs no route
+ # here — the same reason the op is generic. `ALLOWED_APPS` is checked on
+ # the MNP path; here the caller is already on localhost holding the run
+ # token, and `ops` refuses a directory outside the group's roots either
+ # way, so an unknown key writes one unread settings row and nothing else.
+
+ @app.put("/api/groups/{group_id}/app-directories/{app_key}")
+ async def set_app_directories(group_id: str, app_key: str, payload: dict):
+ dirs = payload.get("directories")
+ if not isinstance(dirs, list):
+ raise HTTPException(400, "directories must be a list")
+ return await _op(lambda: ops.set_app_directories(
+ state, group_id, app_key, [str(d) for d in dirs]))
+
+ @app.put("/api/groups/{group_id}/chat-directory")
+ async def set_chat_directory(group_id: str, payload: dict):
+ return await _op(lambda: ops.set_chat_directory(
+ state, group_id, str(payload.get("path") or "")))
+
+ @app.put("/api/groups/{group_id}/chat-link-preview")
+ async def set_chat_link_preview(group_id: str, payload: dict):
+ return await _op(lambda: ops.set_chat_link_preview(
+ state, group_id, bool(payload.get("enabled", True))))
+
# ── Scan settings (operator only, localhost) ──────────────────────────
@app.put("/api/groups/{group_id}/scan-settings")