Skip to content

DEV: fix program manager project detail access - #727

Merged
TThanos3000 merged 1 commit into
devfrom
fix/dev-program-manager-project-detail-access
Sep 6, 2026
Merged

DEV: fix program manager project detail access#727
TThanos3000 merged 1 commit into
devfrom
fix/dev-program-manager-project-detail-access

Conversation

@TThanos3000

Copy link
Copy Markdown
Collaborator

Изменения

Исправлено открытие проектов из manager analytics обычным GET /projects/:id/. Angular/React и контракты аналитики не менялись.

  • Base dev: 4dea5bd8893839e46800f5c9ee20646fc6307aab — подтверждён fetch и повторным remote SHA.
  • Head: 89769ff1b927bb45e41fd5ac94941e80c7d5ea0f.
  • Ветка: fix/dev-program-manager-project-detail-access.
  • Один commit, 3 файла, +264 / −36.

Воспроизведение до fix

Regression-тесты сначала запускались на неизменённом application code текущего dev.

403 на draft/private

ProjectVisibilityPermission разрешал manager/expert связанной программы и staff/superuser, но следующий HasInvolvementInProjectOrReadOnly отклонял draft, если пользователь не leader/collaborator/invite.

Тесты подтвердили 403 вместо ожидаемого 200 для manager, expert, staff и superuser. Integration: тот же project.id возвращался в attention, но detail по нему давал 403.

500 при нескольких program links

GET проекта, доступного лидеру, с двумя PartnerProgramProject воспроизвёл фактический traceback:

ProjectDetail.retrieve -> ProjectDetailSerializer.get_partner_program
project.program_links.select_related("partner_program").get()
PartnerProgramProject.MultipleObjectsReturned:
get() returned more than one PartnerProgramProject -- it returned 2!

Вариант с восемью связями также падал. Это подтверждённая причина воспроизведённого 500 на текущем коде, не catch-all маскировка исключений.

Ограничение диагностики: серверный traceback именно DEV /projects/42/ и реальные данные проектов №42/232 не читались. Совпадение причины конкретного HTTP 500 №42 с этим воспроизведением не заявляется доказанным; для этого нужен runtime traceback. Реальные пользовательские данные не изменялись.

READ и WRITE

Выделен один helper has_project_read_involvement, общий для ограниченной visibility и draft READ gate:

  • leader;
  • staff / superuser;
  • collaborator / invite;
  • manager или expert любой связанной программы.

Он не выдаёт WRITE capabilities. SAFE_METHODS для draft используют helper; существующие ветки PUT/PATCH/DELETE сохранены: опубликованный проект — leader, draft — существующие leader/collaborator/invite. Manager/expert/admin без такого участия не могут изменять или удалять чужой проект.

Приватность опубликованных проектов по-прежнему отдельно проверяет ProjectVisibilityPermission. Публичный флаг не открывает draft постороннему/анониму. Нет создания leader/collaborator/invite/owner или отдельного manager-detail endpoint. Timing permission не менялась семантически.

Black отформатировал существующие длинные выражения внутри изменённого projects/permissions.py; в остальных permissions/модулях функциональных изменений нет.

Legacy partner_program

Singular контракт сохраняется. Выбор:
select_related("partner_program").order_by("pk").first().

  • 0 связей: null;
  • 1 связь: прежний serializer и полный прежний набор полей;
  • 2+ связей: одна с минимальным link.pk (не pk программы), детерминированно;
  • массив программ не добавлен, submission lifecycle не изменён.

Тесты и integration

17 новых тестов (включая subtests) покрывают:

  • draft/private GET для manager/expert/staff-only/superuser-only и существующих leader/collaborator/invite;
  • запрет для outsider, manager/expert другой программы и anonymous;
  • public draft не становится публично читаемым; published private/public поведение сохранено;
  • HEAD/OPTIONS связанного manager;
  • PATCH/PUT/DELETE запрещены manager/expert/admin без project-involvement и для draft, и для published;
  • private draft, чужой leader, manager не collaborator/invite: attention → detail по точному project.id; повторение с той же связью в другой программе;
  • 0/1/2+ links, прежний singular contract, детерминированность по link.pk;
  • SQL count при 1 → 8 links.

SQL

До fix, прогретый detail с одной связью: 17 SQL. После fix: 17 SQL с одной связью и 17 SQL с восемью связями. Первый вызов с созданием View: 20 SQL до и после.

Сам get_partner_program: 3 SQL до/после — JOIN link/program, поля программы, значения полей. Количество не растёт с количеством program links. Queryset detail и list querysets не изменены; новые per-link запросы не добавлены.

Это контролируемый test fixture, не замер live DEV проекта.

Проверки

  • Новые regression tests: 17/17 (включены в targeted и оба полных suite).
  • Targeted project detail/permissions/serializers/relations + analytics: 213 тестов, успешно, 1 существующий PostgreSQL-only skip на SQLite.
  • Локальный полный backend suite: 717 тестов, успешно, 2 существующих PostgreSQL-only skip на SQLite.
  • Backend PostgreSQL CI: успешно на exact head через workflow_dispatch feature-ветки до создания PR. PostgreSQL 15, vendor postgresql, has_select_for_update=True, migrations на пустую БД, 39/39 locking/lifecycle и 717/717 полного suite, без skips. Новые 17 tests выполнены на PostgreSQL в полном suite.
  • Штатный CI: успешно на exact head — полный Flake8 и backend suite (717 тестов, 2 существующих PostgreSQL-only skip на SQLite).
  • Black и Flake8 всех 3 изменённых Python-файлов: успешно.
  • manage.py check, check --tag models, makemigrations --check --dry-run: успешно локально и в PostgreSQL CI, No changes detected.
  • git diff --check, git diff --cached --check, git diff origin/dev...HEAD --check: успешно.

Targeted команда:

python manage.py test projects.tests partner_programs.tests.test_project_apply partner_programs.tests.test_program_project_submit partner_programs.tests.test_project_field_values_api partner_programs.tests.test_manager_analytics_api partner_programs.tests.test_not_submitted_analytics_api partner_programs.tests.test_attention_analytics_api partner_programs.tests.test_assignment_analytics_api --keepdb --noinput --verbosity 1

Локальное окружение: Windows / Python 3.12 / SQLite, существующая внешняя test-only заглушка WeasyPrint из-за отсутствия Pango (не часть PR). Поэтому реальные зависимости отдельно проверены Linux/PostgreSQL CI на Python 3.11. Локальный полный Flake8 5.0.4 выдал 29 диагностик в неизменённых файлах; штатный CI Lint на Python 3.11 уже прошёл по всему репозиторию. Unrelated файлы не исправлялись; dependencies/workflows не менялись.

Границы

Изменены только:

  • projects/permissions.py
  • projects/serializers.py
  • projects/tests/test_program_project_detail_access.py

Не менялись analytics endpoints/contracts и PR #726 logic, frontend/Angular/React, submission/scoring, models/migrations, dependencies, shared modal, workflows, Docker и deploy.

PR остаётся Draft. Merge/deploy не выполнялись.

@TThanos3000
TThanos3000 marked this pull request as ready for review September 6, 2026 10:46
@TThanos3000
TThanos3000 merged commit a12e36b into dev Sep 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant