You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Добавить category-scoped REST-маршрут для мутаций product data из грида «Товары категории», чтобы scope брался из URL, а не из опциональных полей тела запроса.
Предлагаемый контракт:
PUT /api/mgr/categories/{categoryId}/products/{productId}/data
Query/body: nested (0|1) + поля для обновления (как сейчас в PUT /product-data/{id}).
Проблема, которую решает
#444 / #454 закрывают IDOR inline-edit через opt-in проверку: клиент шлёт category_id + nested в body PUT /api/mgr/product-data/{id}.
Недостатки текущего подхода:
Scope client-controlled — backend доверяет body-параметрам, а не контексту маршрута.
Общий endpoint смешивает два сценария: category grid inline-edit и global save из ProductDataFields.vue (без category).
Асимметрия с остальными мутациями грида (/categories/{id}/products/multiple, sort, publish), которые уже category-scoped.
Category-scoped route делает границу категории структурной: нельзя «забыть» передать scope или подменить только id товара.
Предлагаемое решение
Маршрут в config/routes/manager.php:
PUT /categories/{id}/products/{productId}/data → новый метод (например CategoryProductsController::updateProductData или thin delegate).
Описание функции
Добавить category-scoped REST-маршрут для мутаций product data из грида «Товары категории», чтобы scope брался из URL, а не из опциональных полей тела запроса.
Предлагаемый контракт:
Query/body:
nested(0|1) + поля для обновления (как сейчас вPUT /product-data/{id}).Проблема, которую решает
#444 / #454 закрывают IDOR inline-edit через opt-in проверку: клиент шлёт
category_id+nestedв bodyPUT /api/mgr/product-data/{id}.Недостатки текущего подхода:
ProductDataFields.vue(без category)./categories/{id}/products/multiple,sort,publish), которые уже category-scoped.Category-scoped route делает границу категории структурной: нельзя «забыть» передать scope или подменить только id товара.
Предлагаемое решение
config/routes/manager.php:PUT /categories/{id}/products/{productId}/data→ новый метод (напримерCategoryProductsController::updateProductDataили thin delegate).{categoryId}из URL +nestedиз query/body; проверка черезCategoryProductsListService::isProductInCategoryScope()(уже в fix(product-data): category scope для inline-edit PUT #454).useCategoryProductsInlineEditпереключить на новый URL вместо/product-data/{id}+ bodycategory_id.PUT /product-data/{id}оставить дляProductDataFields.vueбез category scope (globalmsproduct_save).category_id/nestedв body глобальногоproduct-dataпосле миграции клиентов.Альтернативы
category_idна всехPUT /product-data/{id}+ явный флагscope=globalдля карточки товара.Примеры использования
Inline-edit в гриде категории 42 (nested):
Карточка товара (без category context) — без изменений:
Критерии приёмки
PermissionMiddleware(msproduct_save) и scope-check по URL categoryId.ProductDataFields— старый route.CategoryProductScopePolicyTest).Дополнительный контекст
PUT /product-data/{id}намеренно остаётся для global product edit; этот issue не про его удаление.