diff options
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py index 4d6dd34..b99affc 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py @@ -1787,7 +1787,7 @@ class WebRTCPeerSession: """ Turn a group "application" on or off for everyone, for this group. - Signed like `member_upload`: this decides what a member sees, and an + Signed like the root ops: this decides what a member sees, and an unsigned message would let any member turn a disabled one back on. """ apps = msg.get("apps") @@ -1799,8 +1799,12 @@ class WebRTCPeerSession: self._send({"type": "error", "detail": f"Unknown app(s): {', '.join(sorted(unknown))}"}) return + # Files is not a toggle: MNP permits root exploration regardless of + # what this list says, so hiding the tab only ever misled. Added at the + # front, the same order ops.set_enabled_apps writes, so the landing-tab + # preference sees one list and not two. if "files" not in apps: - apps.append("files") + apps.insert(0, "files") if not self._has_admin_authority(): self._send({"type": "error", "detail": "No authorized key for this"}) return @@ -1884,7 +1888,7 @@ class WebRTCPeerSession: self._audit("tmdb_config", pending["subject"]) # Node-wide setting: every connected peer in every group is told, not - # just this group's peers (unlike apps_enabled/member_upload/the + # just this group's peers (unlike apps_enabled/the root ops/the # per-group tmdb_enabled below). notice = { "type": MNP.TMDB_CONFIG_ACK, "v": MNP_VERSION, @@ -3795,24 +3799,34 @@ class WebRTCPeerSession: "filename": filename}) return - # The client names the target root. If absent, pick the first writable - # one (backward compat with old clients that don't send it). - target_root_name = msg.get("root") + # The client names the root it is uploading into — it is browsing one, + # and with several writable roots any other choice is a guess. It names + # a root, never a path: the destination inside it is decided below and + # is not negotiable, which is what keeps C5a closed. + # + # An unknown name is refused rather than falling back to a writable + # root, because "the file went somewhere else" is discovered weeks + # later — the same reason the old single upload root was never guessed. + # A client that names nothing is an MNP 1.0 one, and there was exactly + # one destination in its world: the first writable root. + target_root_name = str(msg.get("root") or "").strip() upload_root = None if target_root_name: - from meshbay_common.paths import fold - target_folded = fold(target_root_name) - for r in roots: - if fold(r.name) == target_folded: - upload_root = r - break + upload_root = roots.by_name(target_root_name) + if upload_root is None: + self._send({"type": "error", + "detail": f"No directory named " + f"{target_root_name!r} in this group", + "code": "no_such_root", + "filename": filename}) + return else: writable = roots.writable_roots upload_root = writable[0] if writable else None if upload_root is None: self._send({"type": "error", - "detail": "No writable directory found for uploads", + "detail": "No writable directory in this group", "code": "no_writable_root", "filename": filename}) return @@ -3827,6 +3841,7 @@ class WebRTCPeerSession: self._send({"type": "error", "detail": f"Directory '{upload_root.name}' is " f"currently unavailable", + "code": "root_unavailable", "filename": filename}) return |