aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_hub_api.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_hub_api.py')
-rw-r--r--packages/meshbay-hub/tests/test_hub_api.py45
1 files changed, 34 insertions, 11 deletions
diff --git a/packages/meshbay-hub/tests/test_hub_api.py b/packages/meshbay-hub/tests/test_hub_api.py
index a8232c1..7b75fd1 100644
--- a/packages/meshbay-hub/tests/test_hub_api.py
+++ b/packages/meshbay-hub/tests/test_hub_api.py
@@ -24,6 +24,35 @@ def _gen_user_keys():
)
+
+async def _announce_signed(client, token: str) -> tuple[str, str]:
+ """
+ Announce a node with proof of possession (M8).
+
+ The node key is independent of the user's identity key, so this mints a fresh
+ one and signs the domain-separated announce message with it.
+ """
+ import base64 as _b64, time as _t
+
+ me = await client.get("/v1/users/me",
+ headers={"Authorization": f"Bearer {token}"})
+ user_id = me.json()["user_id"]
+
+ sk_node = Ed25519PrivateKey.generate()
+ pk_node = pk_to_b64(sk_node.public_key())
+ ts = _t.time().__trunc__()
+ msg = f"meshbay:node_announce:{user_id}:{pk_node}:{ts}".encode()
+
+ r = await client.post("/v1/nodes/announce", json={
+ "pk_node": pk_node,
+ "endpoint_hint": "1.2.3.4:19000",
+ "timestamp": ts,
+ "signature": _b64.b64encode(sk_node.sign(msg)).decode(),
+ }, headers={"Authorization": f"Bearer {token}"})
+ assert r.status_code == 201, r.text
+ return r.json()["node_id"], pk_node
+
+
# ── Hub info ──────────────────────────────────────────────────────────────────
@pytest.mark.asyncio
@@ -195,15 +224,12 @@ async def test_announce_and_get_node(client):
token = login.json()["access_token"]
hdrs = {"Authorization": f"Bearer {token}"}
- r = await client.post("/v1/nodes/announce",
- json={"pk_node": pk_ed, "endpoint_hint": "1.2.3.4:19000"},
- headers=hdrs)
- assert r.status_code == 201
- node_id = r.json()["node_id"]
+ node_id, pk_node = await _announce_signed(client, token)
r2 = await client.get(f"/v1/nodes/{node_id}", headers=hdrs)
assert r2.status_code == 200
- assert r2.json()["pk_node"] == pk_ed
+ # The node key is independent of the user identity key (M8).
+ assert r2.json()["pk_node"] == pk_node
assert r2.json()["endpoint_hint"] == "1.2.3.4:19000"
@@ -409,10 +435,7 @@ async def test_group_online_nodes(client):
json={"username": "gn_user", "password": "gnpass999"})).json()["access_token"]
# Announce a node
- r = await client.post("/v1/nodes/announce", json={
- "pk_node": pk_ed, "endpoint_hint": "1.2.3.4:19000"},
- headers={"Authorization": f"Bearer {token}"})
- node_id = r.json()["node_id"]
+ node_id, pk_node = await _announce_signed(client, token)
# No nodes online yet
r = await client.get(f"/v1/groups/{group_id}/nodes",
@@ -433,7 +456,7 @@ async def test_group_online_nodes(client):
nodes = r.json()["nodes"]
assert len(nodes) == 1
assert nodes[0]["node_id"] == node_id
- assert nodes[0]["pk_node"] == pk_ed
+ assert nodes[0]["pk_node"] == pk_node
finally:
_connected_nodes.pop(node_id, None)
_node_groups.pop(node_id, None)