From 39c755089f291416471923725ca29abd2a0ee870 Mon Sep 17 00:00:00 2001
From: Jorge Coutinho
Date: Fri, 1 Nov 2024 13:56:03 -0300
Subject: [PATCH 1/4] add new logic for product_drive deletion
---
app/models/product_drive.rb | 4 ++++
app/views/product_drives/show.html.erb | 6 +++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/app/models/product_drive.rb b/app/models/product_drive.rb
index f9a36a4b87..999694d068 100644
--- a/app/models/product_drive.rb
+++ b/app/models/product_drive.rb
@@ -69,6 +69,10 @@ def self.search_date_range(dates)
@search_date_range = { start_date: dates[0], end_date: dates[1] }
end
+ def can_delete?(user)
+ user.has_role?(Role::ORG_ADMIN, organization) && donations.empty?
+ end
+
# quantities are FILTERED by date then SORTED by name
#
# @param date_range [Range]
diff --git a/app/views/product_drives/show.html.erb b/app/views/product_drives/show.html.erb
index 4153457f04..da244bceb4 100644
--- a/app/views/product_drives/show.html.erb
+++ b/app/views/product_drives/show.html.erb
@@ -90,7 +90,11 @@
From 3aec94e073f2892444abc98e09e9a1e2c4678332 Mon Sep 17 00:00:00 2001
From: Jorge Coutinho
Date: Fri, 1 Nov 2024 13:56:35 -0300
Subject: [PATCH 2/4] add new tests for Product Drive system spec
---
spec/system/product_drive_system_spec.rb | 30 ++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/spec/system/product_drive_system_spec.rb b/spec/system/product_drive_system_spec.rb
index c60bc0122a..67a534e11f 100644
--- a/spec/system/product_drive_system_spec.rb
+++ b/spec/system/product_drive_system_spec.rb
@@ -130,4 +130,34 @@
expect(page).to have_content 'Endless drive'
end
end
+
+ context "when deleting a Product drive" do
+ let(:new_product_drive) { create(:product_drive, name: 'New Test', start_date: 3.weeks.ago, end_date: 3.weeks.from_now, organization: organization) }
+ let(:subject) { product_drive_path(new_product_drive.id) }
+
+ context "when user is a org_admin" do
+ before do
+ user.add_role(:org_admin, organization)
+ end
+
+ it "must delete" do
+ visit subject
+ click_on 'Delete'
+ expect(page).to have_content 'Product drive was successfully destroyed.'
+ end
+
+ it "must not delete if there are donations" do
+ create(:donation, product_drive: new_product_drive)
+ visit subject
+ expect(page).not_to have_button 'Delete'
+ end
+ end
+
+ context "when user is not a org_admin" do
+ it "must not delete" do
+ visit subject
+ expect(page).not_to have_button 'Delete'
+ end
+ end
+ end
end
From cb17ab10a371fa78fae8ded3c56f3acec5113636 Mon Sep 17 00:00:00 2001
From: Jorge Coutinho
Date: Mon, 4 Nov 2024 20:41:22 -0300
Subject: [PATCH 3/4] Implement new role verification and validation for
product drive deletion
---
app/controllers/product_drives_controller.rb | 18 +++++++++-
app/helpers/product_drive_helper.rb | 4 +++
app/models/product_drive.rb | 9 +++--
app/views/product_drives/show.html.erb | 9 +++--
spec/requests/product_drives_requests_spec.rb | 34 ++++++++++++++++---
5 files changed, 62 insertions(+), 12 deletions(-)
diff --git a/app/controllers/product_drives_controller.rb b/app/controllers/product_drives_controller.rb
index 05e55e5dca..67c24a268d 100644
--- a/app/controllers/product_drives_controller.rb
+++ b/app/controllers/product_drives_controller.rb
@@ -1,6 +1,7 @@
class ProductDrivesController < ApplicationController
include Importable
before_action :set_product_drive, only: [:show, :edit, :update, :destroy]
+ before_action :verify_role, only: :destroy
def index
setup_date_range_picker
@@ -76,7 +77,15 @@ def update
end
def destroy
- current_organization.product_drives.find(params[:id]).destroy
+ product_drive = current_organization.product_drives.find(params[:id])
+ product_drive.destroy
+
+ if product_drive.errors.any?
+ flash[:error] = product_drive.errors.full_messages.join("\n")
+ redirect_back(fallback_location: product_drives_url)
+ return
+ end
+
respond_to do |format|
format.html { redirect_to product_drives_url, notice: 'Product drive was successfully destroyed.' }
format.json { head :no_content }
@@ -85,6 +94,13 @@ def destroy
private
+ def verify_role
+ return if current_user.has_role?(Role::ORG_ADMIN, current_organization)
+
+ flash[:error] = 'You are not allowed to perform this action.'
+ redirect_to product_drives_url
+ end
+
# Use callbacks to share common setup or constraints between actions.
def set_product_drive
@product_drive_info = ProductDrive.find(params[:id])
diff --git a/app/helpers/product_drive_helper.rb b/app/helpers/product_drive_helper.rb
index f6dd0c3784..f5b857ab81 100644
--- a/app/helpers/product_drive_helper.rb
+++ b/app/helpers/product_drive_helper.rb
@@ -4,4 +4,8 @@ def is_virtual(product_drive:)
product_drive.virtual? ? 'Yes' : 'No'
end
+
+ def can_delete_product_drive?(user, product_drive)
+ user.has_role?(Role::ORG_ADMIN, product_drive.organization) && product_drive.donations.empty?
+ end
end
diff --git a/app/models/product_drive.rb b/app/models/product_drive.rb
index 999694d068..77353e8e27 100644
--- a/app/models/product_drive.rb
+++ b/app/models/product_drive.rb
@@ -40,6 +40,8 @@ class ProductDrive < ApplicationRecord
validate :end_date_is_bigger_of_end_date
+ before_destroy :validate_destroy, prepend: true
+
def end_date_is_bigger_of_end_date
return if start_date.nil? || end_date.nil?
@@ -69,8 +71,11 @@ def self.search_date_range(dates)
@search_date_range = { start_date: dates[0], end_date: dates[1] }
end
- def can_delete?(user)
- user.has_role?(Role::ORG_ADMIN, organization) && donations.empty?
+ def validate_destroy
+ return if donations.empty?
+
+ errors.add(:base, "Cannot delete product drive with donations.")
+ throw(:abort)
end
# quantities are FILTERED by date then SORTED by name
diff --git a/app/views/product_drives/show.html.erb b/app/views/product_drives/show.html.erb
index da244bceb4..f663d4cbeb 100644
--- a/app/views/product_drives/show.html.erb
+++ b/app/views/product_drives/show.html.erb
@@ -90,11 +90,10 @@
diff --git a/spec/requests/product_drives_requests_spec.rb b/spec/requests/product_drives_requests_spec.rb
index fe6f4476ea..9e5223413c 100644
--- a/spec/requests/product_drives_requests_spec.rb
+++ b/spec/requests/product_drives_requests_spec.rb
@@ -209,11 +209,37 @@
end
describe "DELETE #destroy" do
- it "redirects to the index" do
- product_drive = create(:product_drive, organization: organization)
+ let(:product_drive) { create(:product_drive, organization: organization) }
+
+ context 'when user is not a org_admin' do
+ it "does not delete the product drive" do
+ delete product_drive_path(id: product_drive.id)
+ follow_redirect!
+
+ expect(response.body).to include('You are not allowed to perform this action.')
+ end
+ end
+
+ context 'when user is a org_admin' do
+ before do
+ user.add_role(Role::ORG_ADMIN, organization)
+ end
+
+ it 'deletes the product drive' do
+ delete product_drive_path(id: product_drive.id)
+ follow_redirect!
+
+ expect(response.body).to include('Product drive was successfully destroyed.')
+ end
+
+ it "does not delete the product drive if it has donations" do
+ user.add_role(Role::ORG_ADMIN, organization)
+ create(:donation, product_drive: product_drive)
+ delete product_drive_path(id: product_drive.id)
+ follow_redirect!
- delete product_drive_path(id: product_drive.id)
- expect(response).to redirect_to(product_drives_path)
+ expect(response.body).to include('Cannot delete product drive with donations.')
+ end
end
end
end
From f7b416af05d2cd1f2500cb358c2b50bcd309420d Mon Sep 17 00:00:00 2001
From: Jorge Coutinho
Date: Mon, 4 Nov 2024 20:41:39 -0300
Subject: [PATCH 4/4] Remove product drive deletion tests from system spec
---
spec/system/product_drive_system_spec.rb | 30 ------------------------
1 file changed, 30 deletions(-)
diff --git a/spec/system/product_drive_system_spec.rb b/spec/system/product_drive_system_spec.rb
index 67a534e11f..c60bc0122a 100644
--- a/spec/system/product_drive_system_spec.rb
+++ b/spec/system/product_drive_system_spec.rb
@@ -130,34 +130,4 @@
expect(page).to have_content 'Endless drive'
end
end
-
- context "when deleting a Product drive" do
- let(:new_product_drive) { create(:product_drive, name: 'New Test', start_date: 3.weeks.ago, end_date: 3.weeks.from_now, organization: organization) }
- let(:subject) { product_drive_path(new_product_drive.id) }
-
- context "when user is a org_admin" do
- before do
- user.add_role(:org_admin, organization)
- end
-
- it "must delete" do
- visit subject
- click_on 'Delete'
- expect(page).to have_content 'Product drive was successfully destroyed.'
- end
-
- it "must not delete if there are donations" do
- create(:donation, product_drive: new_product_drive)
- visit subject
- expect(page).not_to have_button 'Delete'
- end
- end
-
- context "when user is not a org_admin" do
- it "must not delete" do
- visit subject
- expect(page).not_to have_button 'Delete'
- end
- end
- end
end