""" Making somebody a member, the way the product does it. An owner adding a username creates an *invitation*; the account becomes a member only when it accepts (`POST /v1/groups/{id}/invitation/accept`). Tests that need a member go through both steps, with a token of the invitee's own — a shortcut that wrote `GroupMember` directly would test a hub where adding someone still made them a member without asking, which is the hole this closed. """ from meshbay_hub.auth import issue_access_token from meshbay_hub.db.engine import get_session_factory from meshbay_hub.db.models import User from sqlalchemy import select async def token_of(username: str) -> str: async with get_session_factory()() as db: uid = await db.scalar(select(User.id).where(User.username == username)) assert uid, f"no such account {username!r}" return issue_access_token(uid) async def accept_invitation(client, group_id: str, username: str) -> None: tok = await token_of(username) r = await client.post(f"/v1/groups/{group_id}/invitation/accept", headers={"Authorization": f"Bearer {tok}"}) assert r.status_code == 200, r.text async def add_member(client, group_id: str, username: str, owner_headers: dict): """Invite, then accept as the invitee. Returns the invitation response.""" r = await client.post(f"/v1/groups/{group_id}/members/{username}", json={}, headers=owner_headers) assert r.status_code in (200, 201), r.text if r.json().get("status") == "invited": await accept_invitation(client, group_id, username) return r