Skip to content

Commit

Permalink
Merge pull request #836 from aviav/fix-entry-policy
Browse files Browse the repository at this point in the history
Allow :create Entry only for publishers on accounts, not on entries
  • Loading branch information
tf authored Aug 28, 2017
2 parents 5f21f8e + b130927 commit 2ef9fd9
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 62 deletions.
2 changes: 1 addition & 1 deletion app/policies/pageflow/entry_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def publish?
end

def create?
publish? && AccountPolicy::Scope.new(user, Account).entry_creatable.any?
query.has_at_least_account_role?(:publisher)
end

def duplicate?
Expand Down
66 changes: 28 additions & 38 deletions spec/policies/pageflow/entry_policy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,167 +5,157 @@ module Pageflow
it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :manage,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :add_member_to,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :edit_role_on,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :destroy_membership_on,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :publish,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :create,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
forbids: :manager,
of_entry: ->(topic) { topic },
to: :create,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :duplicate,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :edit,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :index_widgets_for,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :edit_outline,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :restore,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :snapshot,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :editor,
but_forbids: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :confirm_encoding,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :preview,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :read,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :previewer,
of_entry: -> (topic) { topic },
of_account: -> (topic) { topic.account },
of_entry_or_its_account: ->(topic) { topic },
to: :use_files,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :publish_on_account_of,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :update_account_on,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :publisher,
but_forbids: :editor,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :update_theming_on,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :manage_account_of,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :update_feature_configuration_on,
topic: -> { create(:entry) }

it_behaves_like 'a membership-based permission that',
allows: :manager,
but_forbids: :publisher,
of_account: -> (topic) { topic.account },
of_account: ->(topic) { topic.account },
to: :destroy,
topic: -> { create(:entry) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,82 @@

module Pageflow
shared_examples 'a membership-based permission that' do |params|
let(:user) { create(:user) }
let(:topic) { instance_exec(&params[:topic]) }
let(:entity) { of.call(topic) }
let(:policy) { described_class.new(user, topic) }
allowed_params = [
:allows, :forbids, :but_forbids,
:of_account, :of_entry, :of_entry_or_its_account,
:to, :topic
]

unknown_params = params.keys - allowed_params

if unknown_params.any?
fail("Unknown params: #{unknown_params * ', '}")
end

if params[:of_entry_or_its_account]
params[:of_entry] = params[:of_entry_or_its_account]

params[:of_account] = lambda do |topic|
entry = params[:of_entry_or_its_account].call(topic)
entry.account
end
end

if !params[:of_entry] && !params[:of_account]
fail('Speficy at least one of the following options: of_entry, of_account')
end

params[:forbids] ||= params[:but_forbids]

if !params[:allows] && !params[:forbids]
fail('Specify at least one of the following options: allows, forbids')
end

topic_class_name = described_class.name.humanize.sub('Pageflow::', '').chomp('policy')

let(:user) { create(:user) }
let(:topic) { instance_exec(&params[:topic]) }
let(:entity) { of.call(topic) }
let(:policy) { described_class.new(user, topic) }

[:of_entry, :of_account].each do |membership_type|
if params[membership_type]
next unless params[membership_type]

# This context needs to be here to create a scope for the `let`
# in the next line. Otherwise, when both the `:of_entry` and
# `:of_account` params are present, the second iteration of the
# loop will override the definition of the first, causing the
# specs to be defined for the account case two times.
context do
let(:of) { params[membership_type] }

it "allows #{membership_type == :of_account ? 'account' : 'entry'} #{params[:allows]} " \
"to #{params[:to]} respective " \
"#{described_class.name.humanize.sub('Pageflow::policies::', '').chomp('policy')}" do
create(:membership, user: user, entity: entity, role: params[:allows])
if params[:allows].present?
it "allows #{membership_type == :of_account ? 'account' : 'entry'} #{params[:allows]} " \
"to #{params[:to]} respective #{topic_class_name}" do
create(:membership, user: user, entity: entity, role: params[:allows])

expect(policy).to permit_action(params[:to])
end
expect(policy).to permit_action(params[:to])
end

it "does not allow #{membership_type == :of_account ? 'account' : 'entry'} " \
"#{params[:allows]} to #{params[:to]} off-limits " \
"#{described_class.name.humanize.sub('Pageflow::policies::', '').chomp('policy')}" do
other_entity = (membership_type == :of_entry ? create(:entry) : create(:account))
create(:membership, user: user, entity: other_entity, role: params[:allows])
it "does not allow #{membership_type == :of_account ? 'account' : 'entry'} " \
"#{params[:allows]} to #{params[:to]} off-limits #{topic_class_name}" do
other_entity = (membership_type == :of_entry ? create(:entry) : create(:account))
create(:membership, user: user, entity: other_entity, role: params[:allows])

expect(policy).not_to permit_action(params[:to])
expect(policy).not_to permit_action(params[:to])
end
end

if params[:but_forbids].present?
if params[:forbids].present?
it "does not allow #{membership_type == :of_account ? 'account' : 'entry'} " \
"#{params[:but_forbids]} to #{params[:to]} respective " \
"#{described_class.name.humanize.sub('Pageflow::policies::', '').chomp('policy')}" do
create(:membership, user: user, entity: entity, role: params[:but_forbids])
"#{params[:forbids]} to #{params[:to]} respective #{topic_class_name}" do
create(:membership, user: user, entity: entity, role: params[:forbids])

expect(policy).not_to permit_action(params[:to])
end
else
it 'does not allow user without membership ' \
"to #{params[:to]} respective " \
"#{described_class.name.humanize.sub('Pageflow::policies::', '').chomp('policy')}" do
"to #{params[:to]} respective #{topic_class_name}" do
expect(policy).not_to permit_action(params[:to])
end
end
Expand Down

0 comments on commit 2ef9fd9

Please sign in to comment.