Merge pull request 'F3 UI+sikkerhed: kræv session_token ved guess submit' (#40) from feature/ui-guess-session-token into main
All checks were successful
CI / test-and-quality (push) Successful in 1m27s
All checks were successful
CI / test-and-quality (push) Successful in 1m27s
This commit was merged in pull request #40.
This commit is contained in:
@@ -22,6 +22,6 @@ async function api(path,method,payload){var o={method:method||"GET",headers:{"Ac
|
||||
function joinSession(){return api("/lobby/sessions/join","POST",{code:code(),nickname:document.getElementById("nickname").value.trim()});}
|
||||
function sessionDetail(){return api("/lobby/sessions/"+code(),"GET",null);}
|
||||
function submitLie(){return api("/lobby/sessions/"+code()+"/questions/"+rq()+"/lies/submit","POST",{player_id:parseInt(pid(),10),session_token:document.getElementById("sessionToken").value,text:document.getElementById("lieText").value});}
|
||||
function submitGuess(){return api("/lobby/sessions/"+code()+"/questions/"+rq()+"/guesses/submit","POST",{player_id:parseInt(pid(),10),selected_text:document.getElementById("guessText").value});}
|
||||
function submitGuess(){return api("/lobby/sessions/"+code()+"/questions/"+rq()+"/guesses/submit","POST",{player_id:parseInt(pid(),10),session_token:document.getElementById("sessionToken").value,selected_text:document.getElementById("guessText").value});}
|
||||
</script>
|
||||
</body></html>
|
||||
|
||||
@@ -442,7 +442,7 @@ class GuessSubmissionTests(TestCase):
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Mars"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "selected_text": "Mars"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -461,7 +461,7 @@ class GuessSubmissionTests(TestCase):
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Mars"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "selected_text": "Mars"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -474,7 +474,7 @@ class GuessSubmissionTests(TestCase):
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Venus"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "selected_text": "Venus"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -489,7 +489,7 @@ class GuessSubmissionTests(TestCase):
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Jupiter"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "selected_text": "Jupiter"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -505,7 +505,7 @@ class GuessSubmissionTests(TestCase):
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Mars"},
|
||||
data={"player_id": self.player.id, "session_token": self.player.session_token, "selected_text": "Mars"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
@@ -514,6 +514,33 @@ class GuessSubmissionTests(TestCase):
|
||||
|
||||
|
||||
|
||||
def test_submit_guess_requires_session_token(self):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "selected_text": "Mars"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()["error"], "session_token is required")
|
||||
|
||||
def test_submit_guess_rejects_invalid_session_token(self):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"lobby:submit_guess",
|
||||
kwargs={"code": self.session.code, "round_question_id": self.round_question.id},
|
||||
),
|
||||
data={"player_id": self.player.id, "session_token": "wrong-token", "selected_text": "Mars"},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(response.json()["error"], "Invalid player session token")
|
||||
|
||||
|
||||
class ScoreCalculationTests(TestCase):
|
||||
def setUp(self):
|
||||
self.host = User.objects.create_user(username="host_score", password="secret123")
|
||||
|
||||
@@ -440,11 +440,15 @@ def submit_guess(request: HttpRequest, code: str, round_question_id: int) -> Jso
|
||||
session_code = code.strip().upper()
|
||||
|
||||
player_id = payload.get("player_id")
|
||||
session_token = str(payload.get("session_token", "")).strip()
|
||||
selected_text = str(payload.get("selected_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 selected_text or len(selected_text) > 255:
|
||||
return JsonResponse({"error": "selected_text must be between 1 and 255 characters"}, status=400)
|
||||
|
||||
@@ -461,6 +465,9 @@ def submit_guess(request: HttpRequest, code: str, round_question_id: int) -> Jso
|
||||
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