summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_password_reset.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_password_reset.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_password_reset.py')
-rw-r--r--packages/meshbay-hub/tests/test_password_reset.py72
1 files changed, 36 insertions, 36 deletions
diff --git a/packages/meshbay-hub/tests/test_password_reset.py b/packages/meshbay-hub/tests/test_password_reset.py
index 80977c5..1273315 100644
--- a/packages/meshbay-hub/tests/test_password_reset.py
+++ b/packages/meshbay-hub/tests/test_password_reset.py
@@ -48,22 +48,22 @@ async def _reset_code(db_session, username) -> str:
@pytest.mark.asyncio
async def test_reset_lets_the_user_sign_in_with_a_new_passphrase(client, db_session):
- await _register(client, "alice", "old" + "a" * 41)
- r = await _request_reset(client, "alice")
+ await _register(client, "alice_test", "old" + "a" * 41)
+ r = await _request_reset(client, "alice_test")
assert r.status_code == 200 and r.json()["status"] == "sent_if_exists"
- code = await _reset_code(db_session, "alice")
+ code = await _reset_code(db_session, "alice_test")
assert code
new = "new" + "b" * 41
r = await client.post("/v1/users/password/reset", json={
- "username": "alice", "code": code, "new_auth_key": new})
+ "username": "alice_test", "code": code, "new_auth_key": new})
assert r.status_code == 200, r.text
assert (await client.post("/v1/users/login", json={
- "username": "alice", "auth_key": "old" + "a" * 41})).status_code == 401
+ "username": "alice_test", "auth_key": "old" + "a" * 41})).status_code == 401
assert (await client.post("/v1/users/login", json={
- "username": "alice", "auth_key": new})).status_code == 200
+ "username": "alice_test", "auth_key": new})).status_code == 200
@pytest.mark.asyncio
@@ -78,81 +78,81 @@ async def test_reset_request_never_reveals_whether_an_account_exists(
@pytest.mark.asyncio
async def test_reset_request_needs_the_username_and_email_to_match(client, db_session):
- await _register(client, "hank")
+ await _register(client, "hank_test")
# Right username, wrong e-mail — answered exactly like an unknown account,
# and no code is created.
- r = await _request_reset(client, "hank", email="someone.else@example.com")
+ r = await _request_reset(client, "hank_test", email="someone.else@example.com")
assert r.status_code == 200
assert r.json()["status"] == "sent_if_exists"
assert (await db_session.execute(
select(EmailVerification))).scalars().all() == []
# The real pair does create one.
- await _request_reset(client, "hank")
+ await _request_reset(client, "hank_test")
assert (await db_session.execute(
select(EmailVerification))).scalars().first() is not None
@pytest.mark.asyncio
async def test_reset_request_rejects_a_malformed_email(client):
- await _register(client, "iris")
+ await _register(client, "iris_test")
r = await client.post("/v1/users/password/reset-request", json={
- "username": "iris", "email": "not-an-email"})
+ "username": "iris_test", "email": "not-an-email"})
assert r.status_code == 422
@pytest.mark.asyncio
async def test_a_wrong_code_is_rejected_and_counts_against_the_limit(
client, db_session):
- await _register(client, "bob")
- await _request_reset(client, "bob")
+ await _register(client, "bob_test")
+ await _request_reset(client, "bob_test")
for _ in range(10):
r = await client.post("/v1/users/password/reset", json={
- "username": "bob", "code": "000000", "new_auth_key": "x" * 44})
+ "username": "bob_test", "code": "000000", "new_auth_key": "x" * 44})
assert r.status_code == 400
r = await client.post("/v1/users/password/reset", json={
- "username": "bob", "code": "000000", "new_auth_key": "x" * 44})
+ "username": "bob_test", "code": "000000", "new_auth_key": "x" * 44})
assert r.status_code == 429
@pytest.mark.asyncio
async def test_an_expired_code_is_refused(client, db_session):
- await _register(client, "carol")
- await _request_reset(client, "carol")
+ await _register(client, "carol_test")
+ await _request_reset(client, "carol_test")
uid = (await db_session.execute(
- select(User.id).where(User.username == "carol"))).scalar_one()
+ select(User.id).where(User.username == "carol_test"))).scalar_one()
row = (await db_session.execute(select(EmailVerification).where(
EmailVerification.user_id == uid))).scalars().one()
row.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1)
await db_session.commit()
r = await client.post("/v1/users/password/reset", json={
- "username": "carol", "code": row.code, "new_auth_key": "y" * 44})
+ "username": "carol_test", "code": row.code, "new_auth_key": "y" * 44})
assert r.status_code == 410
@pytest.mark.asyncio
async def test_a_reset_code_works_once(client, db_session):
- await _register(client, "dave")
- await _request_reset(client, "dave")
- code = await _reset_code(db_session, "dave")
+ await _register(client, "dave_test")
+ await _request_reset(client, "dave_test")
+ code = await _reset_code(db_session, "dave_test")
first = await client.post("/v1/users/password/reset", json={
- "username": "dave", "code": code, "new_auth_key": "z" * 44})
+ "username": "dave_test", "code": code, "new_auth_key": "z" * 44})
assert first.status_code == 200
second = await client.post("/v1/users/password/reset", json={
- "username": "dave", "code": code, "new_auth_key": "z" * 44})
+ "username": "dave_test", "code": code, "new_auth_key": "z" * 44})
assert second.status_code == 404
@pytest.mark.asyncio
async def test_reset_revokes_sessions_and_wipes_devices(client, db_session):
- await _register(client, "erin", "erin" + "a" * 40)
+ await _register(client, "erin_test", "erin_test" + "a" * 40)
login = await client.post("/v1/users/login", json={
- "username": "erin", "auth_key": "erin" + "a" * 40})
+ "username": "erin_test", "auth_key": "erin_test" + "a" * 40})
refresh_token = login.json()["refresh_token"]
token = login.json()["access_token"]
@@ -163,10 +163,10 @@ async def test_reset_revokes_sessions_and_wipes_devices(client, db_session):
headers={"Authorization": f"Bearer {token}"})
assert dev.status_code == 201, dev.text
- await _request_reset(client, "erin")
- code = await _reset_code(db_session, "erin")
+ await _request_reset(client, "erin_test")
+ code = await _reset_code(db_session, "erin_test")
r = await client.post("/v1/users/password/reset", json={
- "username": "erin", "code": code, "new_auth_key": "erin-new" + "b" * 36})
+ "username": "erin_test", "code": code, "new_auth_key": "erin-new" + "b" * 36})
assert r.status_code == 200
# Old refresh token is dead.
@@ -175,7 +175,7 @@ async def test_reset_revokes_sessions_and_wipes_devices(client, db_session):
# Every device key is gone; the stored one can no longer sign in.
uid = (await db_session.execute(
- select(User.id).where(User.username == "erin"))).scalar_one()
+ select(User.id).where(User.username == "erin_test"))).scalar_one()
from meshbay_hub.db.models import UserDevice
devices = (await db_session.execute(
select(UserDevice).where(UserDevice.user_id == uid))).scalars().all()
@@ -184,21 +184,21 @@ async def test_reset_revokes_sessions_and_wipes_devices(client, db_session):
ts = int(time.time())
msg = f"meshbay:user_auth:erin:{ts}".encode()
da = await client.post("/v1/users/auth", json={
- "username": "erin", "timestamp": ts,
+ "username": "erin_test", "timestamp": ts,
"signature": base64.b64encode(sk.sign(msg)).decode()})
assert da.status_code == 401
@pytest.mark.asyncio
async def test_the_request_and_the_reset_are_logged(client, db_session):
- await _register(client, "frank")
- await _request_reset(client, "frank")
- code = await _reset_code(db_session, "frank")
+ await _register(client, "frank_test")
+ await _request_reset(client, "frank_test")
+ code = await _reset_code(db_session, "frank_test")
await client.post("/v1/users/password/reset", json={
- "username": "frank", "code": code, "new_auth_key": "f" * 44})
+ "username": "frank_test", "code": code, "new_auth_key": "f" * 44})
uid = (await db_session.execute(
- select(User.id).where(User.username == "frank"))).scalar_one()
+ select(User.id).where(User.username == "frank_test"))).scalar_one()
events = {e.event for e in (await db_session.execute(
select(IPLog).where(IPLog.user_id == uid))).scalars().all()}
assert {"password_reset_request", "password_reset"} <= events