Skip to content

fix(manager): выровнять ответ обновления заказа с GET и скрыть секретный token#426

Open
Ibochkarev wants to merge 3 commits into
betafrom
fix/issue-421-order-update-payload
Open

fix(manager): выровнять ответ обновления заказа с GET и скрыть секретный token#426
Ibochkarev wants to merge 3 commits into
betafrom
fix/issue-421-order-update-payload

Conversation

@Ibochkarev

Copy link
Copy Markdown
Member

Описание

OrdersController::update() (PUT /api/mgr/orders/{id}) возвращал сырой $order->toArray(). Из-за этого:

  • в ответ утекал секретный token заказа (тот же, что ms3_token для авторизации действий над заказом в Web API);
  • форма ответа расходилась с GET /api/mgr/orders/{id}: не было merge адреса, status_name / delivery_name / payment_name, форматированной стоимости — клиент ломался при переиспользовании shape GET.

Изменения:

  • update() формирует ответ через buildOrderPayloadFromModel(), как get() (address-merge, форматирование, отношения).
  • После смены статуса и перезагрузки заказа добавлен guard: если объект не найден, возвращается 500 вместо фатала на toArray().
  • Секретный token убирается из всех Manager-ответов по заказу через HIDDEN_ORDER_FIELDS в общей точке formatOrder() (get, list, create, finalize, recalculate-cost, update).

Изменение контракта: поле token больше не возвращается ни одним Manager order endpoint. Vue-менеджер его не читает (проверено grep по vueManager/src); web-фронт использует ms3_token из cookie/API, а не это поле ответа. Для внешних интеграций это намеренный security-fix.

Тип изменений

  • Исправление бага (non-breaking change)
  • Другое: скрытие секретного поля в ответах Manager API (изменение shape ответа)

Связанные Issues

Closes #421

Как это было протестировано?

  • Автоматические тесты
  • Ручная проверка diff и потребителей ответа

Команды и результат:

php -l .../Controllers/Api/Manager/OrdersController.php   # exit 0
php tests/OrderPayloadSecretFieldsTest.php                # OK (exit 0)
php tests/DirectFilterKeysTest.php                        # OK (exit 0), без регрессий

Регрессия проверена red-green: при возврате formatOrder() без вырезания token тест падает (token must be stripped), после фикса — проходит.

Конфигурация тестирования:

  • MiniShop3: beta / Manager REST
  • MODX: 3.x
  • PHP: 8.2+

Чеклист

  • Код соответствует стилю проекта
  • Изменения не ломают функциональность Vue-менеджера
  • Лексиконы (не требуются — новых пользовательских строк нет)
  • Затронутые PHP-файлы проходят php -l

Дополнительные заметки

Вне scope этого PR (pre-existing, для отдельных задач):

  • update() (~строка 968) и OrderStatusService::change(): непроверенный $order->save() при откате статуса может вернуть success без фактической смены — silent failure.
  • Роут PUT/POST/DELETE /orders защищён только правом msorder_list; разумно развести на msorder_save / msorder_remove.
  • Полей uuid / properties изменения не касаются.

PUT /api/mgr/orders/{id} returned a raw $order->toArray(): the secret
order token leaked and the shape diverged from GET (no address merge,
no formatted cost). Route update() through buildOrderPayloadFromModel()
like GET and add a null-guard after the status-change reload.

Strip the web-order secret token from every Manager order payload via
HIDDEN_ORDER_FIELDS inside the formatOrder() funnel (get, list, create,
finalize, recalculate-cost, update), closing the leak consistently.
@Ibochkarev Ibochkarev added priority: medium Средний приоритет bug Something isn't working labels Jul 17, 2026
@Ibochkarev
Ibochkarev requested a review from biz87 July 17, 2026 09:04
Optional MODX-backed smoke that asserts update() matches GET shape and
that the web-order token never appears in Manager order responses.
Live MODX smoke stays out of the repo; it is environment-specific.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: medium Средний приоритет

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Manager API: PUT /orders/{id} отдаёт raw toArray() (token/shape ≠ GET)

1 participant