From a6ea3719b9b4173ecb39aa812cbdc2b5d128cb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gremaud?= Date: Fri, 16 Oct 2026 01:55:38 +0200 Subject: [PATCH] fix(submissions): default to frontend search to prevent wrong 404 on hard refresh --- polylan_submitter/src/SubmissionsSelect.vue | 24 ++++++++++++-- polylan_submitter/submissions/tests.py | 20 ++++++++++++ polylan_submitter/submissions/views.py | 35 +++------------------ 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/polylan_submitter/src/SubmissionsSelect.vue b/polylan_submitter/src/SubmissionsSelect.vue index e4856fd..32de3c3 100644 --- a/polylan_submitter/src/SubmissionsSelect.vue +++ b/polylan_submitter/src/SubmissionsSelect.vue @@ -28,6 +28,7 @@ const gameName = ref(""); const scopes = ref([]); const loading = ref(true); const notAssigned = ref(false); +const notFound = ref(false); const isSyncModalOpen = ref(false); @@ -49,7 +50,15 @@ const loadScopes = async () => { queryClient.ensureQueryData(userQuery()), ]); - gameName.value = games.find((game) => game.path === props.gamePath)?.name ?? ""; + // Not a game of this event (or one with its own page, not submissions): + // the backend just serves the app for any game path, this is our 404. + const game = games.find((game) => game.path === props.gamePath && !game.custom_path); + if (!game || scopesResponse.error) { + notFound.value = true; + loading.value = false; + return; + } + gameName.value = game.name; const availableScopes = scopesResponse.data ?? []; @@ -74,7 +83,7 @@ onMounted(loadScopes); diff --git a/polylan_submitter/submissions/tests.py b/polylan_submitter/submissions/tests.py index 0f81cf8..7553b72 100644 --- a/polylan_submitter/submissions/tests.py +++ b/polylan_submitter/submissions/tests.py @@ -368,3 +368,23 @@ class ScopeAdminBroadcastTests(TestCase): self.assertEqual( sent, [{"id": str(self.scope.id), "is_active": False, "assigned": False}] ) + + +class SubmissionHomeViewTests(TestCase): + def setUp(self): + self.event = Event.objects.create(name="Event", path="event") + self.client.force_login( + CustomUser.objects.create_user(username="player", password="x") + ) + + def test_any_game_path_serves_the_app(self): + # Unknown game / no scope: the frontend shows its own not-found state + response = self.client.get(f"/{self.event.path}/submissions/unknown-game") + + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "app.html") + + def test_unknown_event_is_404(self): + response = self.client.get("/nope/submissions/unknown-game") + + self.assertEqual(response.status_code, 404) diff --git a/polylan_submitter/submissions/views.py b/polylan_submitter/submissions/views.py index fb8a5e9..57b0209 100644 --- a/polylan_submitter/submissions/views.py +++ b/polylan_submitter/submissions/views.py @@ -1,44 +1,17 @@ from uuid import UUID from django.http import HttpRequest, Http404 -from django.shortcuts import redirect, render, get_object_or_404 +from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from events.models import Event -from games.models import Game from .models import Scope @login_required def submission_home(request: HttpRequest, event_path: str, game_path: str): - event = get_object_or_404(Event, path=event_path) - game = get_object_or_404(Game, path=game_path) - - scopes = ( - Scope.objects.filter( - event_game__event=event, - event_game__game=game, - is_active=True, - ) - if request.user.is_superuser - else Scope.objects.filter( - event_game__event=event, - event_game__game=game, - assigned_users=request.user, - is_active=True, - ) - ) - - if scopes.count() == 1: - return redirect( - "submissions.view", - event_path=event.path, - game_path=game.path, - scope_id=scopes[0].id, - ) - - if not scopes: - raise Http404 - + # Unknown game, no scope assigned, auto-entering the only scope: all + # handled by the frontend (SubmissionsSelect.vue) + get_object_or_404(Event, path=event_path) return render(request, "app.html")