diff options
Diffstat (limited to 'packages/meshbay-node/tests/test_hub_client.py')
| -rw-r--r-- | packages/meshbay-node/tests/test_hub_client.py | 76 |
1 files changed, 13 insertions, 63 deletions
diff --git a/packages/meshbay-node/tests/test_hub_client.py b/packages/meshbay-node/tests/test_hub_client.py index fe8a2af..2975ee8 100644 --- a/packages/meshbay-node/tests/test_hub_client.py +++ b/packages/meshbay-node/tests/test_hub_client.py @@ -2,7 +2,6 @@ Tests for meshbay_node.hub_client — uses httpx.MockTransport to avoid network. """ -import base64 import json import os import time @@ -16,7 +15,7 @@ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey from cryptography.hazmat.primitives import serialization -from meshbay_common.crypto import generate_gek, pk_to_b64, wrap_gek + from meshbay_node.hub_client import HubClient, HubConfig, HubSession from meshbay_node.keystore import NodeKeys @@ -51,16 +50,15 @@ def hub_config(tmp_path): return HubConfig( hub_url="http://fake-hub", username="testuser", - password="testpass99", cache_dir=tmp_path, ) -def make_token(sk_pem, user_id, pk_user_b64, hub_id="fake-hub", ttl=3600): +def make_node_token(sk_pem, user_id, pk_user_b64, hub_id="fake-hub", ttl=3600): now = int(time.time()) return jwt.encode({ "iss": hub_id, "sub": user_id, "pk_user": pk_user_b64, - "hub_id": hub_id, "jti": "test-jti", + "hub_id": hub_id, "jti": "test-jti", "scope": "node", "iat": now, "exp": now + ttl, }, sk_pem, algorithm="EdDSA") @@ -71,14 +69,14 @@ def make_token(sk_pem, user_id, pk_user_b64, hub_id="fake-hub", ttl=3600): async def test_login_verifies_jwt_offline(hub_keys, node_keys, hub_config): sk_hub, sk_hub_pem, pk_hub_pem = hub_keys user_id = "user-uuid-001" - token = make_token(sk_hub_pem, user_id, node_keys.pk_ed25519_b64) + token = make_node_token(sk_hub_pem, user_id, node_keys.pk_ed25519_b64) def handler(request): if request.url.path == "/v1/hub/pubkey": return httpx.Response(200, json={"pk_hub_pem": pk_hub_pem.decode()}) - if request.url.path == "/v1/users/login": + if request.url.path == "/v1/nodes/auth": return httpx.Response(200, json={ - "access_token": token, "refresh_token": "rt-abc", "expires_in": 3600}) + "access_token": token, "token_type": "bearer", "expires_in": 3600}) return httpx.Response(404) transport = httpx.MockTransport(handler) @@ -96,18 +94,18 @@ async def test_login_verifies_jwt_offline(hub_keys, node_keys, hub_config): @pytest.mark.asyncio async def test_login_rejects_missing_jti(hub_keys, node_keys, hub_config): sk_hub, sk_hub_pem, pk_hub_pem = hub_keys - # Token without jti bad_token = jwt.encode({ "iss": "fake-hub", "sub": "uid", "pk_user": node_keys.pk_ed25519_b64, - "hub_id": "fake-hub", "iat": int(time.time()), "exp": int(time.time()) + 3600, + "hub_id": "fake-hub", "scope": "node", + "iat": int(time.time()), "exp": int(time.time()) + 3600, }, sk_hub_pem, algorithm="EdDSA") def handler(request): if request.url.path == "/v1/hub/pubkey": return httpx.Response(200, json={"pk_hub_pem": pk_hub_pem.decode()}) - if request.url.path == "/v1/users/login": + if request.url.path == "/v1/nodes/auth": return httpx.Response(200, json={ - "access_token": bad_token, "refresh_token": "rt", "expires_in": 3600}) + "access_token": bad_token, "token_type": "bearer", "expires_in": 3600}) return httpx.Response(404) transport = httpx.MockTransport(handler) @@ -119,33 +117,16 @@ async def test_login_rejects_missing_jti(hub_keys, node_keys, hub_config): @pytest.mark.asyncio -async def test_register_idempotent(hub_keys, node_keys, hub_config): - def handler(request): - if request.url.path == "/v1/users/register": - return httpx.Response(409, json={"detail": "Username already taken"}) - return httpx.Response(404) - - transport = httpx.MockTransport(handler) - client = HubClient(hub_config, node_keys) - client._http = httpx.AsyncClient(transport=transport, base_url="http://fake-hub") - - # Should not raise on 409 - result = await client.register() - assert result == "" - - -@pytest.mark.asyncio async def test_token_needs_refresh(hub_keys, node_keys, hub_config): sk_hub, sk_hub_pem, pk_hub_pem = hub_keys - # Token expiring in 60s (< TOKEN_REFRESH_MARGIN of 300s) - short_token = make_token(sk_hub_pem, "uid", node_keys.pk_ed25519_b64, ttl=60) + short_token = make_node_token(sk_hub_pem, "uid", node_keys.pk_ed25519_b64, ttl=60) def handler(request): if request.url.path == "/v1/hub/pubkey": return httpx.Response(200, json={"pk_hub_pem": pk_hub_pem.decode()}) - if request.url.path == "/v1/users/login": + if request.url.path == "/v1/nodes/auth": return httpx.Response(200, json={ - "access_token": short_token, "refresh_token": "rt", "expires_in": 60}) + "access_token": short_token, "token_type": "bearer", "expires_in": 60}) return httpx.Response(404) transport = httpx.MockTransport(handler) @@ -157,37 +138,6 @@ async def test_token_needs_refresh(hub_keys, node_keys, hub_config): @pytest.mark.asyncio -async def test_fetch_gek(hub_keys, node_keys, hub_config): - """Admin wraps GEK for this node; client fetches and unwraps.""" - sk_hub, sk_hub_pem, pk_hub_pem = hub_keys - gek = generate_gek() - - # Simulate admin wrapping GEK for this node - pk_x_raw = base64.b64decode(node_keys.pk_x25519_b64) - bundle = wrap_gek(gek, pk_x_raw) - - token = make_token(sk_hub_pem, "uid", node_keys.pk_ed25519_b64) - - def handler(request): - if request.url.path == "/v1/hub/pubkey": - return httpx.Response(200, json={"pk_hub_pem": pk_hub_pem.decode()}) - if request.url.path == "/v1/users/login": - return httpx.Response(200, json={ - "access_token": token, "refresh_token": "rt", "expires_in": 3600}) - if "/v1/groups/" in request.url.path and request.url.path.endswith("/gek"): - return httpx.Response(200, json=bundle) - return httpx.Response(404) - - transport = httpx.MockTransport(handler) - client = HubClient(hub_config, node_keys) - client._http = httpx.AsyncClient(transport=transport, base_url="http://fake-hub") - - await client.login() - recovered = await client.fetch_gek("group-abc") - assert recovered == gek - - -@pytest.mark.asyncio async def test_hub_pk_cached(hub_keys, node_keys, hub_config, tmp_path): _, _, pk_hub_pem = hub_keys call_count = {"n": 0} |