aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_hub_api.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-15 02:16:39 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-15 02:21:01 +0200
commitbdefcd025604f2c3009fe5e0cc01213c2ba62a6a (patch)
treeeebd34aa234a9148045ca25b00bf7c8039e00ccf /packages/meshbay-hub/tests/test_hub_api.py
parent027e7d55f3bb57ba5150fd77e8f0114a0baf8d5c (diff)
downloadmeshbay-bdefcd025604f2c3009fe5e0cc01213c2ba62a6a.tar.gz
feat(hub): usernames are at least 8 characters at registration
Existing shorter accounts keep signing in. Test usernames padded to match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XuNrwLf5EFWCMHzfoEvnpm
Diffstat (limited to 'packages/meshbay-hub/tests/test_hub_api.py')
-rw-r--r--packages/meshbay-hub/tests/test_hub_api.py84
1 files changed, 42 insertions, 42 deletions
diff --git a/packages/meshbay-hub/tests/test_hub_api.py b/packages/meshbay-hub/tests/test_hub_api.py
index 73f7fea..5e9e6c2 100644
--- a/packages/meshbay-hub/tests/test_hub_api.py
+++ b/packages/meshbay-hub/tests/test_hub_api.py
@@ -88,7 +88,7 @@ async def test_hub_pubkey(client):
async def test_register_and_login(client):
pk_ed, pk_x, _ = _gen_user_keys()
r = await client.post("/v1/users/register", json={
- "username": "alice", "email": "alice@example.com",
+ "username": "alice_test", "email": "alice@example.com",
"password": "alicepass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x,
})
@@ -96,7 +96,7 @@ async def test_register_and_login(client):
assert "user_id" in r.json()
r = await client.post("/v1/users/login", json={
- "username": "alice", "password": "alicepass99"})
+ "username": "alice_test", "password": "alicepass99"})
assert r.status_code == 200
data = r.json()
assert "access_token" in data
@@ -107,7 +107,7 @@ async def test_register_and_login(client):
@pytest.mark.asyncio
async def test_register_duplicate_rejected(client):
pk_ed, pk_x, _ = _gen_user_keys()
- body = {"username": "bob", "email": "bob@example.com",
+ body = {"username": "bob_test", "email": "bob@example.com",
"password": "bobpass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x}
await client.post("/v1/users/register", json=body)
@@ -119,11 +119,11 @@ async def test_register_duplicate_rejected(client):
async def test_wrong_password_rejected(client):
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "carol", "email": "carol@example.com",
+ "username": "carol_test", "email": "carol@example.com",
"password": "carolpass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
r = await client.post("/v1/users/login", json={
- "username": "carol", "password": "wrongpass"})
+ "username": "carol_test", "password": "wrongpass"})
assert r.status_code == 401
@@ -133,11 +133,11 @@ async def test_jwt_offline_verify(client, hub_key_path):
import jwt as pyjwt
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "dave", "email": "dave@example.com",
+ "username": "dave_test", "email": "dave@example.com",
"password": "davepass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
r = await client.post("/v1/users/login", json={
- "username": "dave", "password": "davepass99"})
+ "username": "dave_test", "password": "davepass99"})
token = r.json()["access_token"]
r_pk = await client.get("/v1/hub/pubkey")
@@ -155,11 +155,11 @@ async def test_jwt_offline_verify(client, hub_key_path):
async def test_token_refresh(client):
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "eve", "email": "eve@example.com",
+ "username": "eve_test", "email": "eve@example.com",
"password": "evepass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
r = await client.post("/v1/users/login", json={
- "username": "eve", "password": "evepass99"})
+ "username": "eve_test", "password": "evepass99"})
rt = r.json()["refresh_token"]
at = r.json()["access_token"]
@@ -206,17 +206,17 @@ async def test_get_user_pubkeys(client):
"""
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "frank", "email": "frank@example.com",
+ "username": "frank_test", "email": "frank@example.com",
"password": "frankpass99"})
login = await client.post("/v1/users/login", json={
- "username": "frank", "password": "frankpass99"})
+ "username": "frank_test", "password": "frankpass99"})
token = login.json()["access_token"]
- r = await client.get("/v1/users/frank/pubkeys",
+ r = await client.get("/v1/users/frank_test/pubkeys",
headers={"Authorization": f"Bearer {token}"})
assert r.status_code == 200
body = r.json()
- assert body["user_id"] and body["username"] == "frank"
+ assert body["user_id"] and body["username"] == "frank_test"
assert "pk_ed25519" not in body, "user identity keys must not be published (H3)"
assert "pk_x25519" not in body, "user identity keys must not be published (H3)"
@@ -227,11 +227,11 @@ async def test_get_user_pubkeys(client):
async def test_announce_and_get_node(client):
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "node1", "email": "n@example.com",
+ "username": "node1_test", "email": "n@example.com",
"password": "nodepass99",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
login = await client.post("/v1/users/login", json={
- "username": "node1", "password": "nodepass99"})
+ "username": "node1_test", "password": "nodepass99"})
token = login.json()["access_token"]
hdrs = {"Authorization": f"Bearer {token}"}
@@ -253,15 +253,15 @@ async def test_group_member_add(client):
pk_ed_b, pk_x_b, sk_x_b = _gen_user_keys()
for uname, email, pwd, pk_ed, pk_x in [
- ("alice2", "a2@x.com", "alicepass99", pk_ed_a, pk_x_a),
- ("bob2", "b2@x.com", "bobpass99", pk_ed_b, pk_x_b),
+ ("alice2_test", "a2@x.com", "alicepass99", pk_ed_a, pk_x_a),
+ ("bob2_test", "b2@x.com", "bobpass99", pk_ed_b, pk_x_b),
]:
await client.post("/v1/users/register", json={
"username": uname, "email": email, "password": pwd,
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
alice_token = (await client.post("/v1/users/login",
- json={"username": "alice2", "password": "alicepass99"})).json()["access_token"]
+ json={"username": "alice2_test", "password": "alicepass99"})).json()["access_token"]
a_hdrs = {"Authorization": f"Bearer {alice_token}"}
@@ -270,19 +270,19 @@ async def test_group_member_add(client):
group_id = r.json()["group_id"]
# Add bob as member (hub handles membership only, GEK exchange is P2P)
- r = await client.post(f"/v1/groups/{group_id}/members/bob2",
+ r = await client.post(f"/v1/groups/{group_id}/members/bob2_test",
json={}, headers=a_hdrs)
assert r.status_code == 201
# Verify bob is in the group
bob_token = (await client.post("/v1/users/login",
- json={"username": "bob2", "password": "bobpass99"})).json()["access_token"]
+ json={"username": "bob2_test", "password": "bobpass99"})).json()["access_token"]
b_hdrs = {"Authorization": f"Bearer {bob_token}"}
r = await client.get(f"/v1/groups/{group_id}/members", headers=b_hdrs)
assert r.status_code == 200
members = [m["username"] for m in r.json()["members"]]
- assert "alice2" in members
- assert "bob2" in members
+ assert "alice2_test" in members
+ assert "bob2_test" in members
@pytest.mark.asyncio
@@ -291,24 +291,24 @@ async def test_non_admin_cannot_add_member(client):
pk_ed_b, pk_x_b, _ = _gen_user_keys()
for uname, email, pwd, pk_ed, pk_x in [
- ("charlie", "c@x.com", "charliepass", pk_ed_a, pk_x_a),
- ("dan", "d@x.com", "danpass1234", pk_ed_b, pk_x_b),
+ ("charlie_test", "c@x.com", "charliepass", pk_ed_a, pk_x_a),
+ ("dan_test", "d@x.com", "danpass1234", pk_ed_b, pk_x_b),
]:
await client.post("/v1/users/register", json={
"username": uname, "email": email, "password": pwd,
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
charlie_token = (await client.post("/v1/users/login",
- json={"username": "charlie", "password": "charliepass"})).json()["access_token"]
+ json={"username": "charlie_test", "password": "charliepass"})).json()["access_token"]
dan_token = (await client.post("/v1/users/login",
- json={"username": "dan", "password": "danpass1234"})).json()["access_token"]
+ json={"username": "dan_test", "password": "danpass1234"})).json()["access_token"]
r = await client.post("/v1/groups", json={"name": "charlies-group"},
headers={"Authorization": f"Bearer {charlie_token}"})
group_id = r.json()["group_id"]
# Dan (non-admin) tries to add a member → 403
- r = await client.post(f"/v1/groups/{group_id}/members/charlie",
+ r = await client.post(f"/v1/groups/{group_id}/members/charlie_test",
json={},
headers={"Authorization": f"Bearer {dan_token}"})
assert r.status_code == 403
@@ -325,12 +325,12 @@ async def test_jwt_contains_groups_claim(client):
"username": "grp_alice", "email": "ga@x.com", "password": "alicepass99",
"pk_user_ed25519": pk_ed_a, "pk_user_x25519": pk_x_a})
await client.post("/v1/users/register", json={
- "username": "grp_bob", "email": "gb@x.com", "password": "bobpass99",
+ "username": "grp_bob_test", "email": "gb@x.com", "password": "bobpass99",
"pk_user_ed25519": pk_ed_b, "pk_user_x25519": pk_x_b})
# Login before joining any group — groups should be empty
r = await client.post("/v1/users/login", json={
- "username": "grp_bob", "password": "bobpass99"})
+ "username": "grp_bob_test", "password": "bobpass99"})
token_pre = r.json()["access_token"]
r_pk = await client.get("/v1/hub/pubkey")
hub_pk = r_pk.json()["pk_hub_pem"].encode()
@@ -344,13 +344,13 @@ async def test_jwt_contains_groups_claim(client):
headers={"Authorization": f"Bearer {alice_token}"})
group_id = r.json()["group_id"]
- await client.post(f"/v1/groups/{group_id}/members/grp_bob",
+ await client.post(f"/v1/groups/{group_id}/members/grp_bob_test",
json={},
headers={"Authorization": f"Bearer {alice_token}"})
# Login again — groups should contain the new group
r = await client.post("/v1/users/login", json={
- "username": "grp_bob", "password": "bobpass99"})
+ "username": "grp_bob_test", "password": "bobpass99"})
token_post = r.json()["access_token"]
decoded_post = pyjwt.decode(token_post, hub_pk, algorithms=["EdDSA"])
assert group_id in decoded_post["groups"]
@@ -374,13 +374,13 @@ async def test_my_groups(client, db_session):
"username": "mg_alice", "email": "mga@x.com", "password": "alicepass99",
"pk_user_ed25519": pk_ed_a, "pk_user_x25519": pk_x_a})
await client.post("/v1/users/register", json={
- "username": "mg_bob", "email": "mgb@x.com", "password": "bobpass99",
+ "username": "mg_bob_test", "email": "mgb@x.com", "password": "bobpass99",
"pk_user_ed25519": pk_ed_b, "pk_user_x25519": pk_x_b})
alice_token = (await client.post("/v1/users/login",
json={"username": "mg_alice", "password": "alicepass99"})).json()["access_token"]
bob_token = (await client.post("/v1/users/login",
- json={"username": "mg_bob", "password": "bobpass99"})).json()["access_token"]
+ json={"username": "mg_bob_test", "password": "bobpass99"})).json()["access_token"]
# Bob has no groups initially
r = await client.get("/v1/groups/mine",
@@ -392,7 +392,7 @@ async def test_my_groups(client, db_session):
r = await client.post("/v1/groups", json={"name": "mg-group"},
headers={"Authorization": f"Bearer {alice_token}"})
group_id = r.json()["group_id"]
- await client.post(f"/v1/groups/{group_id}/members/mg_bob",
+ await client.post(f"/v1/groups/{group_id}/members/mg_bob_test",
json={},
headers={"Authorization": f"Bearer {alice_token}"})
@@ -406,7 +406,7 @@ async def test_my_groups(client, db_session):
# Re-login to get fresh token with group claims
bob_token = (await client.post("/v1/users/login",
- json={"username": "mg_bob", "password": "bobpass99"})).json()["access_token"]
+ json={"username": "mg_bob_test", "password": "bobpass99"})).json()["access_token"]
# Now Bob should see the group
r = await client.get("/v1/groups/mine",
@@ -439,10 +439,10 @@ async def test_group_online_nodes(client):
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "gn_user", "email": "gn@x.com", "password": "gnpass999",
+ "username": "gn_user_test", "email": "gn@x.com", "password": "gnpass999",
"pk_user_ed25519": pk_ed, "pk_user_x25519": pk_x})
r = await client.post("/v1/users/login",
- json={"username": "gn_user", "password": "gnpass999"})
+ json={"username": "gn_user_test", "password": "gnpass999"})
token = r.json()["access_token"]
r = await client.post("/v1/groups", json={"name": "gn-group"},
@@ -451,7 +451,7 @@ async def test_group_online_nodes(client):
# Re-login to get fresh token with group claims
token = (await client.post("/v1/users/login",
- json={"username": "gn_user", "password": "gnpass999"})).json()["access_token"]
+ json={"username": "gn_user_test", "password": "gnpass999"})).json()["access_token"]
# Announce a node
node_id, pk_node = await _announce_signed(client, token)
@@ -816,7 +816,7 @@ async def test_register_no_credentials_rejected(client):
"""Registration without auth_key or password returns 400."""
pk_ed, pk_x, _ = _gen_user_keys()
r = await client.post("/v1/users/register", json={
- "username": "nocred",
+ "username": "nocred_test",
"email": "nocred@test.com",
"pk_user_ed25519": pk_ed,
"pk_user_x25519": pk_x,
@@ -868,7 +868,7 @@ async def test_login_v3_account_password_only_rejected(client):
"""Login with raw password to a v3 (auth_key) account returns 401."""
pk_ed, pk_x, _ = _gen_user_keys()
await client.post("/v1/users/register", json={
- "username": "v3nopw",
+ "username": "v3nopw_test",
"email": "v3nopw@test.com",
"auth_key": "dGVzdGF1dGhrZXl0ZXN0YXV0aGtleXRlc3RhdXRo",
"pk_user_ed25519": pk_ed,
@@ -876,7 +876,7 @@ async def test_login_v3_account_password_only_rejected(client):
})
r = await client.post("/v1/users/login", json={
- "username": "v3nopw", "password": "somepassword"})
+ "username": "v3nopw_test", "password": "somepassword"})
assert r.status_code == 401
@@ -955,7 +955,7 @@ async def test_login_legacy_migration(client, app):
@pytest.mark.asyncio
async def test_login_no_credentials_rejected(client):
"""Login without auth_key or password returns 401."""
- r = await client.post("/v1/users/login", json={"username": "nobody"})
+ r = await client.post("/v1/users/login", json={"username": "nobody_test"})
assert r.status_code == 401
assert "No credentials" in r.json()["detail"]