feat(f3): require player session token for lie submission
This commit is contained in:
@@ -55,6 +55,8 @@ class LobbyFlowTests(TestCase):
|
||||
body = response.json()
|
||||
self.assertEqual(body["session"]["code"], "ABCD23")
|
||||
self.assertEqual(body["player"]["nickname"], "Luna")
|
||||
self.assertIn("session_token", body["player"])
|
||||
self.assertTrue(body["player"]["session_token"])
|
||||
self.assertTrue(Player.objects.filter(session=session, nickname="Luna").exists())
|
||||
|
||||
def test_join_rejects_duplicate_nickname_case_insensitive(self):
|
||||
@@ -217,7 +219,7 @@ class LieSubmissionTests(TestCase):
|
||||
"lobby:submit_lie",
|
||||
kwargs={"code": self.session.code, "round_question_id": round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "text": "Sydney"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "text": "Sydney"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -239,7 +241,7 @@ class LieSubmissionTests(TestCase):
|
||||
"lobby:submit_lie",
|
||||
kwargs={"code": self.session.code, "round_question_id": round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "text": "Melbourne"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "text": "Melbourne"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -260,13 +262,53 @@ class LieSubmissionTests(TestCase):
|
||||
"lobby:submit_lie",
|
||||
kwargs={"code": self.session.code, "round_question_id": round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "text": "Brisbane"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "text": "Brisbane"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 409)
|
||||
self.assertEqual(response.json()["error"], "Lie already submitted for this player")
|
||||
|
||||
def test_submit_lie_requires_session_token(self):
|
||||
round_question = RoundQuestion.objects.create(
|
||||
session=self.session,
|
||||
round_number=1,
|
||||
question=self.question,
|
||||
correct_answer=self.question.correct_answer,
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"lobby:submit_lie",
|
||||
kwargs={"code": self.session.code, "round_question_id": round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "text": "Sydney"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()["error"], "session_token is required")
|
||||
|
||||
def test_submit_lie_rejects_invalid_session_token(self):
|
||||
round_question = RoundQuestion.objects.create(
|
||||
session=self.session,
|
||||
round_number=1,
|
||||
question=self.question,
|
||||
correct_answer=self.question.correct_answer,
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"lobby:submit_lie",
|
||||
kwargs={"code": self.session.code, "round_question_id": round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "session_token": "invalid-token", "text": "Sydney"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(response.json()["error"], "Invalid player session token")
|
||||
|
||||
class MixAnswersTests(TestCase):
|
||||
def setUp(self):
|
||||
self.host = User.objects.create_user(username="host", password="secret123")
|
||||
|
||||
@@ -104,6 +104,7 @@ def join_session(request: HttpRequest) -> JsonResponse:
|
||||
"player": {
|
||||
"id": player.id,
|
||||
"nickname": player.nickname,
|
||||
"session_token": player.session_token,
|
||||
"score": player.score,
|
||||
},
|
||||
"session": {
|
||||
@@ -296,11 +297,15 @@ def submit_lie(request: HttpRequest, code: str, round_question_id: int) -> JsonR
|
||||
session_code = code.strip().upper()
|
||||
|
||||
player_id = payload.get("player_id")
|
||||
session_token = str(payload.get("session_token", "")).strip()
|
||||
lie_text = str(payload.get("text", "")).strip()
|
||||
|
||||
if not player_id:
|
||||
return JsonResponse({"error": "player_id is required"}, status=400)
|
||||
|
||||
if not session_token:
|
||||
return JsonResponse({"error": "session_token is required"}, status=400)
|
||||
|
||||
if not lie_text or len(lie_text) > 255:
|
||||
return JsonResponse({"error": "text must be between 1 and 255 characters"}, status=400)
|
||||
|
||||
@@ -317,6 +322,9 @@ def submit_lie(request: HttpRequest, code: str, round_question_id: int) -> JsonR
|
||||
except Player.DoesNotExist:
|
||||
return JsonResponse({"error": "Player not found in session"}, status=404)
|
||||
|
||||
if player.session_token != session_token:
|
||||
return JsonResponse({"error": "Invalid player session token"}, status=403)
|
||||
|
||||
try:
|
||||
round_question = RoundQuestion.objects.get(
|
||||
pk=round_question_id,
|
||||
|
||||
Reference in New Issue
Block a user