Skip to content

Commit 7776008

Browse files
authored
Merge pull request #4354 from manyfold3d/fix-permission-bug
Fix permission bug where contributors could edit things they didn't have permission to
2 parents 15e60d2 + a51658a commit 7776008

File tree

9 files changed

+54
-38
lines changed

9 files changed

+54
-38
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ gem "devise_zxcvbn", "~> 6.0"
156156

157157
gem "federails", git: "https://gitlab.com/experimentslabs/federails.git", branch: "merge-contexts"
158158
gem "federails-moderation", "~> 0.3"
159-
gem "caber"
159+
gem "caber", github: "manyfold3d/caber"
160160

161161
gem "nanoid", "~> 2.0"
162162

Gemfile.lock

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ GIT
77
capybara (>= 1.0, < 4)
88
launchy
99

10+
GIT
11+
remote: https://github.com/manyfold3d/caber.git
12+
revision: 501a9f4dba0df4772f41713fc69cfc8ec470a7ba
13+
specs:
14+
caber (0.4.0)
15+
rails (>= 7.1.4)
16+
1017
GIT
1118
remote: https://github.com/manyfold3d/rubocop-pundit.git
1219
revision: 10ac81bbec63a9abd3d58be84dc47d9c490b29c6
@@ -182,8 +189,6 @@ GEM
182189
activesupport (>= 3.0.0)
183190
uniform_notifier (~> 1.11)
184191
byebug (12.0.0)
185-
caber (0.4.0)
186-
rails (>= 7.1.4)
187192
capybara (3.40.0)
188193
addressable
189194
matrix
@@ -910,7 +915,7 @@ DEPENDENCIES
910915
brakeman (~> 7.0)
911916
bullet (~> 8.0)
912917
byebug
913-
caber
918+
caber!
914919
capybara
915920
capybara-screenshot!
916921
climate_control (~> 1.2)

app/components/model_card.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ class Components::ModelCard < Components::Base
77

88
register_output_helper :status_badges
99
register_output_helper :server_indicator
10+
register_value_helper :policy
1011

11-
def initialize(model:, can_edit: false, can_destroy: false)
12+
def initialize(model:)
1213
@model = model
13-
@can_destroy = can_destroy
14-
@can_edit = can_edit
1514
end
1615

1716
def view_template
@@ -111,8 +110,8 @@ def actions
111110
end
112111
div class: "col col-auto" do
113112
BurgerMenu do
114-
DropdownItem(icon: "pencil", label: t("components.model_card.edit_button.text"), path: edit_model_path(@model), aria_label: translate("components.model_card.edit_button.label", name: @model.name)) if @can_edit
115-
DropdownItem(icon: "trash", label: t("components.model_card.delete_button.text"), path: model_path(@model), method: :delete, aria_label: translate("components.model_card.delete_button.label", name: @model.name), confirm: translate("models.destroy.confirm")) if @can_destroy
113+
DropdownItem(icon: "pencil", label: t("components.model_card.edit_button.text"), path: edit_model_path(@model), aria_label: translate("components.model_card.edit_button.label", name: @model.name)) if policy(@model).edit?
114+
DropdownItem(icon: "trash", label: t("components.model_card.delete_button.text"), path: model_path(@model), method: :delete, aria_label: translate("components.model_card.delete_button.label", name: @model.name), confirm: translate("models.destroy.confirm")) if policy(@model).destroy?
116115
DropdownItem(icon: "flag", label: t("general.report", type: ""), path: new_model_report_path(@model)) if SiteSettings.multiuser_enabled?
117116
end
118117
end

app/controllers/concerns/model_listable.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ module ModelListable
99
private
1010

1111
def prepare_model_list
12-
# Work out policies for showing buttons up front
13-
@can_destroy = policy(Model).destroy?
14-
@can_edit = policy(Model).edit?
15-
1612
# Ordering
1713
@models = case session["order"]
1814
when "recent"

app/views/models/_list.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<% end %>
1515
</div>
1616
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 mb-4">
17-
<%= render_component_collection Components::ModelCard, :model, @models, can_edit: @can_edit, can_destroy: @can_destroy %>
17+
<%= render_component_collection Components::ModelCard, :model, @models %>
1818
</div>
1919
<% if pagination_settings["models"] %>
2020
<%= paginate @models %>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "rails_helper"
2+
3+
describe CollectionPolicy do
4+
let(:target_class) { Collection }
5+
6+
it_behaves_like "ApplicationPolicy"
7+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "rails_helper"
2+
3+
describe CreatorPolicy do
4+
let(:target_class) { Creator }
5+
6+
it_behaves_like "ApplicationPolicy"
7+
end

spec/policies/model_policy_spec.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
describe ModelPolicy do
44
subject(:policy) { described_class }
55

6-
let(:member) { create(:user) }
7-
let(:moderator) { create(:moderator) }
8-
let(:model) { create(:model) }
6+
let(:target_class) { Model }
7+
98
let(:nested) { create(:model) }
9+
let(:model) { create(:model) }
10+
let(:moderator) { create(:moderator) }
11+
let(:member) { create(:user) }
12+
13+
it_behaves_like "ApplicationPolicy"
1014

1115
permissions :destroy? do
1216
it "denies deletion to users with member role" do
Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
require "rails_helper"
2-
3-
describe ApplicationPolicy do
1+
shared_examples "ApplicationPolicy" do
42
subject(:policy) { described_class }
53

64
let(:member) { create(:user) }
7-
let(:model) { create(:model) }
5+
let(:object) { create(target_class.to_s.underscore.to_sym) }
86

97
permissions :index?, :show? do
108
it "allows users with member role by default" do
11-
expect(policy).to permit(member, model)
9+
expect(policy).to permit(member, object)
1210
end
1311

1412
it "falls back to member role if ReBAC isn't available on the record" do
@@ -18,27 +16,27 @@
1816

1917
context "when default member role access is removed" do
2018
before do
21-
model.revoke_permission("view", Role.find_by(name: :member))
19+
object.revoke_permission("view", Role.find_by(name: :member))
2220
end
2321

2422
it "denies users without individual view permission" do
25-
expect(policy).not_to permit(member, model)
23+
expect(policy).not_to permit(member, object)
2624
end
2725

2826
it "allows users with individual view permission" do
29-
model.grant_permission_to "view", member
30-
expect(policy).to permit(member, model)
27+
object.grant_permission_to "view", member
28+
expect(policy).to permit(member, object)
3129
end
3230
end
3331

3432
context "with an unknown user" do
3533
it "denies access if public view permission isn't set" do
36-
expect(policy).not_to permit(nil, model)
34+
expect(policy).not_to permit(nil, object)
3735
end
3836

3937
it "allows access if public view permission is set" do
40-
model.grant_permission_to "view", nil
41-
expect(policy).to permit(nil, model)
38+
object.grant_permission_to "view", nil
39+
expect(policy).to permit(nil, object)
4240
end
4341
end
4442
end
@@ -64,26 +62,26 @@
6462
let(:contributor) { create(:contributor) }
6563

6664
it "allows all users with moderator role" do
67-
expect(policy).to permit(moderator, model)
65+
expect(policy).to permit(moderator, object)
6866
end
6967

7068
it "denies users with contributor role" do
71-
expect(policy).not_to permit(contributor, model)
69+
expect(policy).not_to permit(contributor, object)
7270
end
7371

7472
it "allows users with granted edit permission" do
75-
model.grant_permission_to "edit", member
76-
expect(policy).to permit(member, model)
73+
object.grant_permission_to "edit", member
74+
expect(policy).to permit(member, object)
7775
end
7876

7977
it "allows users with granted owner permission" do
80-
model.grant_permission_to "own", member
81-
expect(policy).to permit(member, model)
78+
object.grant_permission_to "own", member
79+
expect(policy).to permit(member, object)
8280
end
8381

84-
it "denies unknown users on public models" do
85-
model.grant_permission_to "view", nil
86-
expect(policy).not_to permit(nil, model)
82+
it "denies unknown users on public objects" do
83+
object.grant_permission_to "view", nil
84+
expect(policy).not_to permit(nil, object)
8785
end
8886
end
8987
end

0 commit comments

Comments
 (0)