diff --git a/app/controllers/spree/orders_controller.rb b/app/controllers/spree/orders_controller.rb index cb1cf63d64..d982d5a0e8 100644 --- a/app/controllers/spree/orders_controller.rb +++ b/app/controllers/spree/orders_controller.rb @@ -107,7 +107,7 @@ module Spree def cancel @order = Spree::Order.find_by!(number: params[:id]) - authorize! :cancel, @order + authorize! :cancel, @order, session[:access_token] if Orders::CustomerCancellationService.new(@order).call flash[:success] = I18n.t(:orders_your_order_has_been_cancelled) diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index e6f797fe45..d24006d625 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -113,7 +113,11 @@ module Spree item.order.changes_allowed? end - can [:cancel, :bulk_cancel], Spree::Order do |order| + can :cancel, Spree::Order do |order, token| + order.user == user || (order.token && token == order.token) + end + + can :bulk_cancel, Spree::Order do |order| order.user == user end diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 630a73eade..c6528315e3 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -461,14 +461,34 @@ RSpec.describe Spree::OrdersController do end end + context "when a guest user has the order token in session" do + let(:order) { + create(:completed_order_with_totals, user: nil, email: "guest@example.com", + distributor: create(:distributor_enterprise)) + } + + before do + allow(controller).to receive(:spree_current_user) { nil } + session[:access_token] = order.token + end + + it "cancels the order and redirects to the order page" do + request.env['HTTP_REFERER'] = order_path(order) + spree_put :cancel, params + + expect(response.body).to match(order_path(order)).and match("redirect") + expect(flash[:success]).to eq 'Your order has been cancelled' + end + end + context "when the user has permission to cancel the order" do before { allow(controller).to receive(:spree_current_user) { user } } context "when the order is not yet complete" do it "responds with forbidden" do + request.env['HTTP_REFERER'] = order_path(order) spree_put :cancel, params - expect(response).to have_http_status(:found) expect(response.body).to match(order_path(order)).and match("redirect") expect(flash[:error]).to eq 'Sorry, the order could not be cancelled' end @@ -481,9 +501,9 @@ RSpec.describe Spree::OrdersController do } it "responds with success" do + request.env['HTTP_REFERER'] = order_path(order) spree_put :cancel, params - expect(response).to have_http_status(:found) expect(response.body).to match(order_path(order)).and match("redirect") expect(flash[:success]).to eq 'Your order has been cancelled' end