""" Editing a group's description. A description could only be set when the group was created, so every group made before anyone thought to write one stayed blank for good. What is deliberately *not* editable is as much the point: name, visibility and join policy are the terms members joined on. """ import base64 import hashlib import pytest def _auth_key(password: str, username: str) -> str: salt = hashlib.sha256(f"meshbay:auth:v1:{username}".encode()).digest() return base64.b64encode( hashlib.pbkdf2_hmac("sha512", password.encode(), salt, 600_000, 32)).decode() async def _user(client, username, password="a-long-enough-passphrase"): await client.post("/v1/users/register", json={ "username": username, "email": f"{username}@example.com", "auth_key": _auth_key(password, username)}) r = await client.post("/v1/users/login", json={ "username": username, "auth_key": _auth_key(password, username)}) return {"Authorization": f"Bearer {r.json()['access_token']}"} async def _group(client, headers, name="described", **kw): r = await client.post("/v1/groups", json={"name": name, **kw}, headers=headers) return r.json()["group_id"] @pytest.mark.asyncio async def test_the_owner_can_write_a_description(client): owner = await _user(client, "writer") gid = await _group(client, owner) r = await client.patch(f"/v1/groups/{gid}", json={"description": "host grenoble"}, headers=owner) assert r.status_code == 200, r.text mine = await client.get("/v1/groups/mine", headers=owner) group = next(g for g in mine.json()["groups"] if g["id"] == gid) assert group["description"] == "host grenoble" @pytest.mark.asyncio async def test_a_member_cannot(client): owner = await _user(client, "owner2") member = await _user(client, "member2") gid = await _group(client, owner, name="not-yours") await client.post(f"/v1/groups/{gid}/members/member2", json={}, headers=owner) r = await client.patch(f"/v1/groups/{gid}", json={"description": "mine now"}, headers=member) assert r.status_code == 403 @pytest.mark.asyncio async def test_an_empty_description_clears_it(client): owner = await _user(client, "clearer") gid = await _group(client, owner, name="clearme", description="temporary") r = await client.patch(f"/v1/groups/{gid}", json={"description": " "}, headers=owner) assert r.status_code == 200 assert r.json()["description"] == "" @pytest.mark.asyncio async def test_the_terms_members_joined_on_are_not_editable(client): """ A private group that could quietly become public is not the group its members agreed to be in. Changing that needs a decision about who gets told, so the endpoint ignores it rather than half-implementing it. """ owner = await _user(client, "sneaky") gid = await _group(client, owner, name="private-please", visibility="private") await client.patch(f"/v1/groups/{gid}", json={"description": "hi", "visibility": "public", "join_policy": "open", "name": "renamed"}, headers=owner) mine = await client.get("/v1/groups/mine", headers=owner) group = next(g for g in mine.json()["groups"] if g["id"] == gid) assert group["visibility"] == "private" assert group["join_policy"] == "invite" assert group["name"] == "private-please" @pytest.mark.asyncio async def test_a_long_description_is_truncated_not_refused(client): owner = await _user(client, "verbose") gid = await _group(client, owner, name="long") r = await client.patch(f"/v1/groups/{gid}", json={"description": "x" * 900}, headers=owner) assert r.status_code == 200 assert len(r.json()["description"]) == 512