From 9fe9c6da4d8c1e8ec0a729c3ea5009ca64103017 Mon Sep 17 00:00:00 2001 From: Jage9 Date: Sat, 28 Feb 2026 20:17:49 -0500 Subject: [PATCH] Allow valid self-target item transfers --- server/app/server.py | 3 -- server/tests/test_server_message_handling.py | 57 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/server/app/server.py b/server/app/server.py index 4da06a3..d559bd9 100644 --- a/server/app/server.py +++ b/server/app/server.py @@ -2506,9 +2506,6 @@ class SignalingServer: if not target or not target.authenticated or not target.user_id: await self._send_item_result(client, False, "transfer", "Target user is not available.", item.id) return - if target.id == client.id: - await self._send_item_result(client, False, "transfer", "Cannot transfer an item to yourself.", item.id) - return if item.createdBy == target.user_id: await self._send_item_result(client, False, "transfer", "Item already belongs to that user.", item.id) return diff --git a/server/tests/test_server_message_handling.py b/server/tests/test_server_message_handling.py index b2d62b4..401006a 100644 --- a/server/tests/test_server_message_handling.py +++ b/server/tests/test_server_message_handling.py @@ -392,6 +392,63 @@ async def test_item_transfer_updates_item_owner(monkeypatch: pytest.MonkeyPatch) assert "owner transferred" in getattr(broadcast_payloads[-1], "message", "").lower() +@pytest.mark.asyncio +async def test_item_transfer_allows_self_target_for_transfer_any(monkeypatch: pytest.MonkeyPatch) -> None: + server = SignalingServer("127.0.0.1", 8765, None, None, grid_size=41) + owner_ws = _fake_ws() + actor_ws = _fake_ws() + owner = ClientConnection( + websocket=owner_ws, + id="u1", + nickname="owner", + authenticated=True, + user_id="1", + username="owner_user", + permissions=set(), + x=5, + y=6, + ) + actor = ClientConnection( + websocket=actor_ws, + id="u3", + nickname="actor", + authenticated=True, + user_id="3", + username="actor_user", + permissions={"item.transfer.any"}, + x=5, + y=6, + ) + server.clients[owner_ws] = owner + server.clients[actor_ws] = actor + item = server.item_service.default_item(owner, "dice") + item.x = actor.x + item.y = actor.y + server.item_service.add_item(item) + + send_payloads: list[object] = [] + broadcasted_items: list[object] = [] + + async def fake_send(websocket: ServerConnection, packet: object) -> None: + send_payloads.append(packet) + + async def fake_broadcast_item(broadcast_item: object) -> None: + broadcasted_items.append(broadcast_item) + + monkeypatch.setattr(server, "_send", fake_send) + monkeypatch.setattr(server, "_broadcast_item", fake_broadcast_item) + + await server._handle_message(actor, json.dumps({"type": "item_transfer", "itemId": item.id, "targetId": actor.id})) + + assert item.createdBy == actor.user_id + assert item.createdByName == actor.username + assert broadcasted_items + result = send_payloads[-1] + assert result.type == "item_action_result" + assert result.ok is True + assert result.action == "transfer" + + @pytest.mark.asyncio async def test_item_delete_sends_others_notification(monkeypatch: pytest.MonkeyPatch) -> None: server = SignalingServer("127.0.0.1", 8765, None, None, grid_size=41)