summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/hub_client.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/hub_client.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/hub_client.py42
1 files changed, 42 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/hub_client.py b/packages/meshbay-node/src/meshbay_node/hub_client.py
index 58bf657..06d3503 100644
--- a/packages/meshbay-node/src/meshbay_node/hub_client.py
+++ b/packages/meshbay-node/src/meshbay_node/hub_client.py
@@ -85,6 +85,11 @@ class HubClient:
async def __aenter__(self):
return self
+ @property
+ def hub_url(self) -> str:
+ """The hub's address as this node was configured with it."""
+ return self._config.hub_url
+
async def __aexit__(self, *_):
await self.close()
@@ -258,6 +263,43 @@ class HubClient:
r.raise_for_status()
return r.json()
+ async def create_invite_link(self, group_id: str, email: str, expires_at: str,
+ node_invite_id: str) -> dict:
+ """
+ The hub's half of an invitation link: a ticket bound to `email`.
+
+ Never with `send_email`: the hub refuses mail to a node token, and the
+ CLI mails nothing — the operator sends the link (docs/USERGUIDE.md §7).
+ """
+ if self._session is None:
+ raise RuntimeError("Not logged in")
+ await self.ensure_fresh_token()
+ r = await self._http.post(
+ f"/v1/groups/{group_id}/invite-links",
+ json={"email": email, "expires_at": expires_at,
+ "node_invite_id": node_invite_id},
+ headers=self._session.auth_headers,
+ )
+ r.raise_for_status()
+ return r.json()
+
+ async def list_invite_links(self, group_id: str) -> list[dict]:
+ if self._session is None:
+ raise RuntimeError("Not logged in")
+ await self.ensure_fresh_token()
+ r = await self._http.get(f"/v1/groups/{group_id}/invite-links",
+ headers=self._session.auth_headers)
+ r.raise_for_status()
+ return r.json().get("links", [])
+
+ async def delete_invite_link(self, group_id: str, link_id: str) -> None:
+ if self._session is None:
+ raise RuntimeError("Not logged in")
+ await self.ensure_fresh_token()
+ r = await self._http.delete(f"/v1/groups/{group_id}/invite-links/{link_id}",
+ headers=self._session.auth_headers)
+ r.raise_for_status()
+
# ── Persistent WebSocket (signaling + revocations) ──────────────────────
async def send_ws(self, data: str) -> None: