From 1b8cb1297201865c9bba879a67a8578e75d821e8 Mon Sep 17 00:00:00 2001 From: Fedor Date: Sun, 8 Nov 2026 19:44:35 +0300 Subject: [PATCH] Check dev routes and keep the notification inbox quiet with V2 archived --- .github/workflows/dev-ci.yml | 7 ++++++- partner_programs/solution_invitation_api.py | 17 ++++++++++------- partner_programs/tests/test_program_launch.py | 5 +++++ scripts/check_dev_routes.py | 7 ++++--- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 935752dd..870c91d7 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -341,7 +341,12 @@ jobs: exit 1 fi && - if ! python3 scripts/check_dev_routes.py https://dev.procollab.ru; then + solution_templates_status="$( + docker compose -f docker-compose.dev-ci.yml exec -T web python -c \ + 'from procollab.settings import PROGRAM_SOLUTIONS_ENABLED; print(401 if PROGRAM_SOLUTIONS_ENABLED else 404)' + )" + if ! python3 scripts/check_dev_routes.py https://dev.procollab.ru \ + --solution-templates-status "$solution_templates_status"; then echo "Frontend/API routing smoke check failed" >&2 exit 1 fi && diff --git a/partner_programs/solution_invitation_api.py b/partner_programs/solution_invitation_api.py index 6c279ddd..bd0c4ef9 100644 --- a/partner_programs/solution_invitation_api.py +++ b/partner_programs/solution_invitation_api.py @@ -1,8 +1,10 @@ """HTTP-контракт C00 для принадлежащих решению приглашений.""" +from django.conf import settings from django.http import Http404 from rest_framework import serializers from rest_framework.exceptions import ValidationError +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from partner_programs import solution_invitations, solution_team @@ -208,15 +210,16 @@ def post(self, request, pk, solution_id): class MySolutionInvitationsView(SolutionAPIView): + # The global inbox keeps its pagination contract when V2 is archived. + permission_classes = [IsAuthenticated] + def get(self, request): - return Response( - invitation_page( - solution_invitations.visible_invitations(request.user).filter( - recipient=request.user - ), - request, - ) + invites = solution_invitations.visible_invitations(request.user).filter( + recipient=request.user ) + if not settings.PROGRAM_SOLUTIONS_ENABLED: + invites = invites.none() + return Response(invitation_page(invites, request)) class SolutionInvitationDetailView(SolutionAPIView): diff --git a/partner_programs/tests/test_program_launch.py b/partner_programs/tests/test_program_launch.py index b6341053..a9346f41 100644 --- a/partner_programs/tests/test_program_launch.py +++ b/partner_programs/tests/test_program_launch.py @@ -66,6 +66,11 @@ def test_v1_switch_selects_project_templates_and_archives_v2_routes(self): ) archived.refresh_from_db() self.assertEqual(archived.solution_storage_mode, "solution") + inbox = self.client.get("/solution-invitations/") + self.assertEqual(inbox.status_code, 200) + self.assertEqual(inbox.data, {"count": 0, "next": None, "previous": None, "results": []}) + self.client.force_authenticate(None) + self.assertEqual(self.client.get("/solution-invitations/").status_code, 401) def test_all_formats_start_private_without_fake_dates_and_enrollment(self): for kind in ("case_championship", "hackathon", "noncompetitive"): diff --git a/scripts/check_dev_routes.py b/scripts/check_dev_routes.py index be24410f..2edba986 100644 --- a/scripts/check_dev_routes.py +++ b/scripts/check_dev_routes.py @@ -30,7 +30,7 @@ def request(base_url, path, method="GET", context=None): return response.status, response.headers.get_content_type(), response.read() -def check_routes(base_url, context=None): +def check_routes(base_url, context=None, *, solution_templates_status=401): status, content_type, index = request(base_url, "/", context=context) assert status == 200 and content_type == "text/html" and b"