Skip to content

Commit aea6f9e

Browse files
alecslupuahukkanen
andauthored
Backport 'Refactor amendment permissions' to v0.30 (decidim#15168)
Co-authored-by: Antti Hukkanen <antti.hukkanen@mainiotech.fi>
1 parent 902f2aa commit aea6f9e

8 files changed

Lines changed: 202 additions & 11 deletions

File tree

decidim-core/app/commands/decidim/amendable/accept.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ def update_amendable!
6262
@amendable.save!
6363
@amendable
6464
end
65-
@amendable.add_coauthor(@amender, user_group: @user_group)
65+
66+
@amendable.add_coauthor(@amender, user_group: @user_group) if @amendable.is_a?(Decidim::Coauthorable)
6667
end
6768

6869
def notify_emendation_state_change!

decidim-core/app/controllers/decidim/amendments_controller.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def publish_draft
107107
end
108108

109109
def reject
110-
enforce_permission_to :reject, :amendment, current_component: amendable.component
110+
enforce_permission_to :reject, :amendment, amendable:, current_component: amendable.component
111111

112112
@form = form(Decidim::Amendable::RejectForm).from_model(amendment)
113113

@@ -143,13 +143,13 @@ def promote
143143
end
144144

145145
def review
146-
enforce_permission_to :accept, :amendment, current_component: amendable.component
146+
enforce_permission_to :accept, :amendment, amendable:, current_component: amendable.component
147147

148148
@form = form(Decidim::Amendable::ReviewForm).from_params(params)
149149
end
150150

151151
def accept
152-
enforce_permission_to :accept, :amendment, current_component: amendable.component
152+
enforce_permission_to :accept, :amendment, amendable:, current_component: amendable.component
153153

154154
@form = form(Decidim::Amendable::ReviewForm).from_params(params)
155155

decidim-core/app/helpers/decidim/amendments_helper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ def can_react_to_emendation?(emendation)
6161
# Checks if the user can accept and reject the emendation
6262
def allowed_to_accept_and_reject?(emendation)
6363
return unless emendation.amendment.evaluating?
64+
return current_user.admin? if emendation.amendable.respond_to?(:official?) && emendation.amendable.official?
6465

65-
emendation.amendable.created_by?(current_user) || current_user.admin?
66+
emendation.amendable.created_by?(current_user)
6667
end
6768

6869
# Checks if the user can promote the emendation

decidim-core/app/permissions/decidim/permissions.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,19 @@ def amend_action?
106106
return allow! if component.current_settings.amendment_creation_enabled
107107
when :accept,
108108
:reject
109-
return allow! if component.current_settings.amendment_reaction_enabled
109+
return disallow! unless component.current_settings.amendment_reaction_enabled
110+
111+
amendable = context.fetch(:amendable, nil)
112+
113+
if amendable.respond_to?(:official?) && amendable.official?
114+
return allow! if user.admin?
115+
116+
return disallow!
117+
end
118+
119+
return disallow! unless amendable.authored_by?(user)
120+
121+
return allow!
110122
when :promote
111123
return allow! if component.current_settings.amendment_promotion_enabled
112124
end

decidim-core/spec/controllers/amendments_controller_spec.rb

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,5 +234,132 @@ module Decidim
234234
end
235235
end
236236
end
237+
238+
describe "GET review" do
239+
context "when the user is NOT the creator of the resource" do
240+
let(:user) { other_user }
241+
242+
it "does not allow access" do
243+
get(:review, params:)
244+
245+
expect(response).to have_http_status(:redirect)
246+
expect(flash[:alert]).to eq("You are not authorized to perform this action.")
247+
end
248+
end
249+
250+
context "when the user is the creator of the resource" do
251+
let(:user) { amendable.author }
252+
253+
it "allows access" do
254+
get(:review, params:)
255+
256+
expect(response).to have_http_status(:ok)
257+
end
258+
end
259+
end
260+
261+
describe "PATCH accept" do
262+
let(:emendation_params) { { title: emendation.title, body: emendation.body } }
263+
264+
context "when the user is NOT the creator of the resource" do
265+
let(:user) { other_user }
266+
267+
it "does not accept the amendment" do
268+
patch :accept, params: params.merge(emendation_params:)
269+
270+
expect(response).to have_http_status(:redirect)
271+
expect(flash[:alert]).to eq("You are not authorized to perform this action.")
272+
end
273+
end
274+
275+
context "when the user is the creator of the resource" do
276+
let(:user) { amendable.author }
277+
278+
it "accepts the amendment" do
279+
patch :accept, params: params.merge(emendation_params:)
280+
281+
expect(response).to have_http_status(:redirect)
282+
expect(flash[:notice]).to eq("The amendment has been accepted successfully.")
283+
end
284+
end
285+
286+
context "when the resource is official" do
287+
let!(:amendable) { create(:dummy_resource, component:, author: component.organization) }
288+
289+
context "and the user is NOT an admin" do
290+
let(:user) { amendment.amender }
291+
292+
it "does not accept the amendment" do
293+
patch :accept, params: params.merge(emendation_params:)
294+
295+
expect(response).to have_http_status(:redirect)
296+
expect(flash[:alert]).to eq("You are not authorized to perform this action.")
297+
end
298+
end
299+
300+
context "and the user is an admin" do
301+
let(:user) { create(:user, :confirmed, :admin, organization: component.organization) }
302+
303+
it "accepts the amendment" do
304+
patch :accept, params: params.merge(emendation_params:)
305+
306+
expect(response).to have_http_status(:redirect)
307+
expect(flash[:notice]).to eq("The amendment has been accepted successfully.")
308+
end
309+
end
310+
end
311+
end
312+
313+
describe "PATCH reject" do
314+
let(:emendation_params) { { title: emendation.title, body: emendation.body } }
315+
316+
context "when the user is NOT the creator of the resource" do
317+
let(:user) { other_user }
318+
319+
it "does not accept the amendment" do
320+
patch :reject, params: params.merge(emendation_params:)
321+
322+
expect(response).to have_http_status(:redirect)
323+
expect(flash[:alert]).to eq("You are not authorized to perform this action.")
324+
end
325+
end
326+
327+
context "when the user is the creator of the resource" do
328+
let(:user) { amendable.author }
329+
330+
it "accepts the amendment" do
331+
patch :reject, params: params.merge(emendation_params:)
332+
333+
expect(response).to have_http_status(:redirect)
334+
expect(flash[:notice]).to eq("The amendment has been successfully rejected.")
335+
end
336+
end
337+
338+
context "when the resource is official" do
339+
let!(:amendable) { create(:dummy_resource, component:, author: component.organization) }
340+
341+
context "and the user is NOT an admin" do
342+
let(:user) { amendment.amender }
343+
344+
it "does not accept the amendment" do
345+
patch :reject, params: params.merge(emendation_params:)
346+
347+
expect(response).to have_http_status(:redirect)
348+
expect(flash[:alert]).to eq("You are not authorized to perform this action.")
349+
end
350+
end
351+
352+
context "and the user is an admin" do
353+
let(:user) { create(:user, :confirmed, :admin, organization: component.organization) }
354+
355+
it "accepts the amendment" do
356+
patch :reject, params: params.merge(emendation_params:)
357+
358+
expect(response).to have_http_status(:redirect)
359+
expect(flash[:notice]).to eq("The amendment has been successfully rejected.")
360+
end
361+
end
362+
end
363+
end
237364
end
238365
end

decidim-core/spec/permissions/decidim/permissions_spec.rb

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,11 @@
197197
context "when an amend action" do
198198
let(:component) { create(:component, :published, organization: user.organization, settings:) }
199199
let(:settings) { { amendments_enabled: } }
200-
let(:amendment) { create(:amendment) }
201-
let(:user) { amendment.amender }
202-
let(:context) { { current_component: component } }
200+
let(:amendable) { build(:dummy_resource, component:) }
201+
let(:emendation) { build(:dummy_resource, component:) }
202+
let(:amendment) { create(:amendment, emendation:, amendable:, amender: user) }
203+
let(:user) { create(:user) }
204+
let(:context) { { amendable: amendment.amendable, current_component: component } }
203205
let(:action_name) { nil }
204206
let(:action) do
205207
{ scope: :public, action: action_name, subject: :amendment }
@@ -217,13 +219,49 @@
217219
context "with a accept action" do
218220
let(:action_name) { :accept }
219221

220-
it { is_expected.to be true }
222+
it { is_expected.to be false }
223+
224+
context "when the amendable is authored by the user" do
225+
before { amendment.amendable.update!(author: user) }
226+
227+
it { is_expected.to be true }
228+
end
229+
230+
context "with an official amendable" do
231+
let(:amendable) { build(:dummy_resource, component:, author: component.organization) }
232+
233+
it { is_expected.to be false }
234+
235+
context "and the user is an admin" do
236+
let(:user) { create(:user, :confirmed, :admin) }
237+
238+
it { is_expected.to be true }
239+
end
240+
end
221241
end
222242

223243
context "with a reject action" do
224244
let(:action_name) { :reject }
225245

226-
it { is_expected.to be true }
246+
it { is_expected.to be false }
247+
248+
context "when the amendable is authored by the user" do
249+
before { amendment.amendable.update!(author: user) }
250+
251+
it { is_expected.to be true }
252+
end
253+
254+
context "with an official amendable" do
255+
let(:amendable) { build(:dummy_resource, component:, author: component.organization) }
256+
257+
it { is_expected.to be false }
258+
259+
context "and the user is an admin" do
260+
let(:user) { create(:user, :confirmed, :admin) }
261+
262+
it { is_expected.to be true }
263+
end
264+
end
227265
end
228266

229267
context "with a promote action" do

decidim-dev/app/models/decidim/dev/dummy_resource.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ class DummyResource < ApplicationRecord
4242

4343
component_manifest_name "dummy"
4444

45+
alias creator_author author
46+
47+
def creator
48+
self
49+
end
50+
51+
def authors
52+
[author]
53+
end
54+
4555
def presenter
4656
Decidim::Dev::DummyResourcePresenter.new(self)
4757
end

decidim-proposals/spec/system/amendable/amend_proposal_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@
207207
let!(:user_group) { create(:user_group, :verified, organization: user.organization, users: [user]) }
208208

209209
before do
210+
expect(page).to have_content("Log in")
211+
switch_to_host(component.organization.host)
210212
login_as user, scope: :user
211213
visit proposal_path
212214
expect(page).to have_content(proposal_title)

0 commit comments

Comments
 (0)