mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-26 01:33:22 +00:00
Refactor order management permissions for producers
Introduces granular permissions control for producers editing orders: - Adds new :edit_as_producer_only permission for suppliers - Refactors ability checks to clearly separate producer vs admin/distributor access - Updates order views to properly restrict actions based on user role - Prevents admins from being restricted by producer-only edit mode
This commit is contained in:
@@ -155,8 +155,7 @@ module Spree
|
||||
end
|
||||
|
||||
def filter_by_supplier?(order)
|
||||
order.distributor&.enable_producers_to_edit_orders &&
|
||||
spree_current_user.can_manage_line_items_in_orders_only?
|
||||
can? :edit_as_producer_only, order
|
||||
end
|
||||
|
||||
def display_value_for_producer(order, value)
|
||||
|
||||
@@ -20,6 +20,10 @@ module Spree
|
||||
|
||||
if user.try(:admin?)
|
||||
can :manage, :all
|
||||
|
||||
# this action was needed for restrictions for distributors and suppliers
|
||||
# however, admins don't need to be restricted, so, bypassing it for admins
|
||||
cannot :edit_as_producer_only, Spree::Order
|
||||
else
|
||||
can [:index, :read], Country
|
||||
can :create, Order
|
||||
@@ -257,8 +261,13 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_cycle_management_abilities(user)
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include?(order_cycle) ||
|
||||
order_cycle.orders.any? { |order| can_edit_as_producer(order, user) }
|
||||
end
|
||||
|
||||
can [
|
||||
:admin, :index, :read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
:read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include? order_cycle
|
||||
end
|
||||
@@ -274,8 +283,37 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_management_abilities(user)
|
||||
can [:index, :create], Spree::Order
|
||||
can [:read, :update, :fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
can [:manage_order_sections], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
order.distributor.nil? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
|
||||
can [:edit_as_producer_only], Spree::Order do |order|
|
||||
cannot?(:manage_order_sections, order) && can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:index], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:create], Spree::Order
|
||||
|
||||
can [:read, :update], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
# Enterprise User can access orders that they are a distributor for
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
@@ -284,22 +322,39 @@ module Spree
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
can [:admin, :bulk_management, :managed, :distribution], Spree::Order do
|
||||
|
||||
can [:admin, :bulk_management], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:managed, :distribution], Spree::Order do
|
||||
user.admin? || user.enterprises.any?(&:is_distributor)
|
||||
end
|
||||
can [:admin, :index, :create, :show, :poll, :generate], :invoice
|
||||
can [:admin, :visible], Enterprise
|
||||
can [:admin, :index, :create, :update, :destroy], :line_item
|
||||
can [:admin, :index, :create], Spree::LineItem
|
||||
can [:admin, :index, :create], Spree::LineItem do |item|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:destroy, :update], Spree::LineItem do |item|
|
||||
order = item.order
|
||||
user.admin? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment do |shipment|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
|
||||
can [:destroy], Spree::Adjustment do |adjustment|
|
||||
@@ -350,26 +405,31 @@ module Spree
|
||||
can [:admin, :edit, :cancel, :resume], ProxyOrder do |proxy_order|
|
||||
user.enterprises.include?(proxy_order.subscription.shop)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
def can_edit_order(order, user)
|
||||
def can_edit_as_producer(order, user)
|
||||
return unless order.distributor&.enable_producers_to_edit_orders
|
||||
|
||||
order.variants.any? { |variant| user.enterprises.ids.include?(variant.supplier_id) }
|
||||
end
|
||||
|
||||
def add_manage_line_items_abilities(user)
|
||||
can [:edit_as_producer_only], Spree::Order do |order|
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:admin, :read, :index, :edit, :update, :bulk_management], Spree::Order do |order|
|
||||
can_edit_order(order, user)
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
can [:admin, :index, :create, :destroy, :update], Spree::LineItem do |item|
|
||||
can_edit_order(item.order, user)
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:index, :create, :add, :read, :edit, :update], Spree::Shipment do |shipment|
|
||||
can_edit_order(shipment.order, user)
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
can_edit_order(order_cycle.order, user)
|
||||
can_edit_as_producer(order_cycle.order, user)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- if @order.shipments.any?
|
||||
= render :partial => "spree/admin/orders/shipment", :collection => @order.shipments, :locals => { :order => @order }
|
||||
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
- if @order.line_items.exists?
|
||||
= render partial: "spree/admin/orders/note", locals: { order: @order }
|
||||
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
- if local_assigns[:success]
|
||||
%i.success.icon-ok-sign{"data-controller": "ephemeral"}
|
||||
= render AdminTooltipComponent.new(text: t('spree.admin.orders.index.edit'), link_text: "", link: edit_admin_order_path(order), link_class: "icon_link with-tip icon-edit no-text")
|
||||
- if spree_current_user.can_manage_orders? && order.ready_to_ship?
|
||||
- if can?(:manage_order_sections, order) && order.ready_to_ship?
|
||||
%form
|
||||
= render ShipOrderComponent.new(order: order)
|
||||
= render partial: 'admin/shared/tooltip_button', locals: {button_class: "icon-road icon_link with-tip no-text", reflex_data_id: order.id.to_s, tooltip_text: t('spree.admin.orders.index.ship'), shipment: true}
|
||||
|
||||
- if can?(:update, Spree::Payment) && order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any?
|
||||
- if can?(:manage_order_sections, order) && can?(:update, Spree::Payment) && order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any?
|
||||
= render partial: 'admin/shared/tooltip_button', locals: {button_class: "icon-capture icon_link no-text", button_reflex: "click->Admin::OrdersReflex#capture", reflex_data_id: order.id.to_s, tooltip_text: t('spree.admin.orders.index.capture')}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- content_for :page_actions do
|
||||
- if can?(:fire, @order)
|
||||
%li= event_links(@order)
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
= render partial: 'spree/admin/shared/order_links'
|
||||
- if can?(:admin, Spree::Order)
|
||||
%li
|
||||
@@ -14,7 +14,7 @@
|
||||
= t(:back_to_orders_list)
|
||||
|
||||
= render partial: "spree/admin/shared/order_page_title"
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
= render partial: "spree/admin/shared/order_tabs", locals: { current: 'Order Details' }
|
||||
|
||||
%div
|
||||
@@ -22,7 +22,12 @@
|
||||
|
||||
= admin_inject_shops(@shops, module: 'admin.orders')
|
||||
= admin_inject_order_cycles(@order_cycles)
|
||||
%div{"ng-controller" => "orderCtrl", "ofn-distributor-id" => @order.distributor_id, "ofn-order-cycle-id" => @order.order_cycle_id}
|
||||
%div{
|
||||
"ng-controller" => "orderCtrl",
|
||||
"ofn-distributor-id" => @order.distributor_id,
|
||||
"ofn-order-cycle-id" => @order.order_cycle_id,
|
||||
"ofn-search-variants-as" => (can?(:manage_order_sections, @order) ? 'hub' : 'supplier'),
|
||||
}
|
||||
|
||||
= render :partial => 'add_product' if can?(:update, @order)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user