From 25d55fec24ebf61305992c5c6b7699f2eae879b3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 Oct 2025 15:06:53 +1100 Subject: [PATCH] Filter out variant the user is not allowed to update With a product with mutiple variant, we can end in a scenario where a user sees variant associated to producer it doesn't have permission for. This prevents the user from updating any variant. This fix filter out variant a user shoudn't be seeing --- app/controllers/admin/products_v3_controller.rb | 17 +++++++++++------ app/views/admin/products_v3/_content.html.haml | 4 ++-- .../products_v3/_product_variant_row.html.haml | 4 +++- app/views/admin/products_v3/_table.html.haml | 4 ++-- app/views/admin/products_v3/index.html.haml | 8 +++++--- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb index 6d1ae388cb..7656c8709f 100644 --- a/app/controllers/admin/products_v3_controller.rb +++ b/app/controllers/admin/products_v3_controller.rb @@ -11,7 +11,8 @@ module Admin def index fetch_products render "index", - locals: { producers:, categories:, tax_category_options:, available_tags:, flash: } + locals: { producer_options:, categories:, tax_category_options:, available_tags:, + flash:, allowed_producers: } session[:products_return_to_url] = request.url end @@ -32,7 +33,8 @@ module Admin render "index", status: :unprocessable_entity, locals: { - producers:, categories:, tax_category_options:, available_tags:, flash: + producer_options:, categories:, tax_category_options:, available_tags:, + flash: } end end @@ -88,7 +90,7 @@ module Admin flash.now[:success] = t('.success') @product_index = "-#{@cloned_product.id}" - @producer_options = producers + @producer_options = producer_options @category_options = categories @tax_category_options = tax_category_options rescue ActiveRecord::ActiveRecordError => e @@ -132,10 +134,13 @@ module Admin end end - def producers - producers = OpenFoodNetwork::Permissions.new(spree_current_user) + def allowed_producers + OpenFoodNetwork::Permissions.new(spree_current_user) .managed_product_enterprises.is_primary_producer.by_name - producers.map { |p| [p.name, p.id] } + end + + def producer_options + allowed_producers.map { |p| [p.name, p.id] } end def categories diff --git a/app/views/admin/products_v3/_content.html.haml b/app/views/admin/products_v3/_content.html.haml index d54148c508..3a84d074c0 100644 --- a/app/views/admin/products_v3/_content.html.haml +++ b/app/views/admin/products_v3/_content.html.haml @@ -1,4 +1,4 @@ --# locals: (products:, pagy:, search_term:, producer_options:, producer_id:, category_options:, category_id:, tax_category_options:, available_tags:, tags:, flashes:, display_search_filter:) +-# locals: (products:, pagy:, search_term:, producer_options:, producer_id:, category_options:, category_id:, tax_category_options:, available_tags:, tags:, flashes:, display_search_filter:, allowed_producers:) %turbo-frame#products-content{ target: "_top", refresh: "morph" } .spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" } .spinner-container @@ -18,7 +18,7 @@ .container.results .sixteen.columns = render partial: 'sort', locals: { pagy:, search_term:, producer_id:, category_id:, tags: } - = render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: } + = render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: , allowed_producers: } - if pagy.present? && pagy.pages > 1 = render partial: 'admin/shared/stimulus_pagination', locals: { pagy: pagy } - else diff --git a/app/views/admin/products_v3/_product_variant_row.html.haml b/app/views/admin/products_v3/_product_variant_row.html.haml index 5879b8124f..722abb2af7 100644 --- a/app/views/admin/products_v3/_product_variant_row.html.haml +++ b/app/views/admin/products_v3/_product_variant_row.html.haml @@ -1,4 +1,4 @@ --# locals: (form:, product:, product_index:, producer_options:, category_options:, tax_category_options:) +-# locals: (form:, product:, product_index:, producer_options:, category_options:, tax_category_options:, allowed_producers:) = form.fields_for("products", product, index: product_index) do |product_form| %tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id, controller: "nested-form product", @@ -8,6 +8,8 @@ = render partial: 'product_row', locals: { f: product_form, product:, product_index: } - product.variants.each_with_index do |variant, variant_index| + + - next unless allowed_producers.include?(variant.supplier) = form.fields_for("products][#{product_index}][variants_attributes", variant, index: variant_index) do |variant_form| %tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false } = render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: } diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 92a1ea9393..7d2750a5a9 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -1,4 +1,4 @@ --# locals: (products:, producer_options:, category_options:, tax_category_options:) +-# locals: (products:, producer_options:, category_options:, tax_category_options:, allowed_producers:) = form_with url: admin_products_bulk_update_path, method: :post, id: "products-form", builder: BulkFormBuilder, html: { data: { 'turbo-frame': "_self", @@ -70,4 +70,4 @@ %th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties') %th.align-right= t('admin.products_page.columns.actions') - products.each_with_index do |product, product_index| - = render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: } + = render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: , allowed_producers:} diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 6193139b5a..04d992e3d4 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -1,4 +1,4 @@ --# locals: (producers:, categories:, tax_category_options:, available_tags:, flash:) +-# locals: (producer_options:, categories:, tax_category_options:, available_tags:, flash:, allowed_producers:) - content_for :page_title do = t('.header.title') - content_for :page_actions do @@ -14,11 +14,13 @@ #products_v3_page{ 'data-turbo': true } = render partial: "content", locals: { products: @products, pagy: @pagy, search_term: @search_term, - producer_options: producers, producer_id: @producer_id, + producer_options:, producer_id: @producer_id, category_options: categories, category_id: @category_id, tax_category_options:, available_tags:, tags: @tags, flashes: flash, - display_search_filter: (@products.any? || @search_term.present? || @category_id.present?) } + display_search_filter: (@products.any? || @search_term.present? || @category_id.present?), + allowed_producers:} + - %w[product variant].each do |object_type| = render partial: 'delete_modal', locals: { object_type: } #modal-component