diff options
| -rw-r--r-- | app/decorators/referential_decorator.rb | 53 | ||||
| -rw-r--r-- | app/policies/referential_policy.rb | 4 | ||||
| -rw-r--r-- | spec/decorators/referential_decorator_spec.rb | 76 | ||||
| -rw-r--r-- | spec/policies/referential_policy_spec.rb | 97 | ||||
| -rw-r--r-- | spec/support/decorator_helpers.rb | 32 | 
5 files changed, 216 insertions, 46 deletions
| diff --git a/app/decorators/referential_decorator.rb b/app/decorators/referential_decorator.rb index b95b04f9f..64016ee61 100644 --- a/app/decorators/referential_decorator.rb +++ b/app/decorators/referential_decorator.rb @@ -2,6 +2,7 @@ class ReferentialDecorator < Draper::Decorator    delegate_all    def action_links +    policy = h.policy(object)      links = [        Link.new(          content: h.t('time_tables.index.title'), @@ -9,40 +10,42 @@ class ReferentialDecorator < Draper::Decorator        )      ] -    if h.policy(object).clone? +    if policy.clone?        links << Link.new(          content: h.t('actions.clone'),          href: h.new_referential_path(from: object.id)        )      end -    if h.policy(object).edit? +    if policy.archive? +      links << Link.new( +        content: h.t('actions.archive'), +        href: h.archive_referential_path(object.id), +        method: :put +      ) +    end + +    if policy.unarchive? +      links << Link.new( +        content: h.t('actions.unarchive'), +        href: h.unarchive_referential_path(object.id), +        method: :put +      ) +    end -      if object.archived? -        links << Link.new( -          content: h.t('actions.unarchive'), -          href: h.unarchive_referential_path(object.id), -          method: :put -        ) -      else -        links << HTMLElement.new( -          :button, -          'Purger', -          type: 'button', -          data: { -            toggle: 'modal', -            target: '#purgeModal' -          } -        ) -        links << Link.new( -          content: h.t('actions.archive'), -          href: h.archive_referential_path(object.id), -          method: :put -        ) -      end +    if policy.edit? +      links << HTMLElement.new( +        :button, +        'Purger', +        type: 'button', +        data: { +          toggle: 'modal', +          target: '#purgeModal' +        } +      )      end -    if h.policy(object).destroy? && !object.archived? +    if policy.destroy?        links << Link.new(          content: h.destroy_link_content,          href: h.referential_path(object), diff --git a/app/policies/referential_policy.rb b/app/policies/referential_policy.rb index bf970c2b8..9d0a92093 100644 --- a/app/policies/referential_policy.rb +++ b/app/policies/referential_policy.rb @@ -24,11 +24,11 @@ class ReferentialPolicy < ApplicationPolicy    end    def archive? -    record.archived_at.nil? && user.has_permission?('referentials.update') +    record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')    end    def unarchive? -    !record.archived_at.nil? && user.has_permission?('referentials.update') +    !record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')    end    def common_lines? diff --git a/spec/decorators/referential_decorator_spec.rb b/spec/decorators/referential_decorator_spec.rb new file mode 100644 index 000000000..5de6b7e95 --- /dev/null +++ b/spec/decorators/referential_decorator_spec.rb @@ -0,0 +1,76 @@ +RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do + +  let( :object ){ build_stubbed :referential } +  let( :referential ){ object } +  let( :user ){ build_stubbed :user } + +  describe 'delegation' do +    it 'delegates all' do +      %i{xx xxx anything save!}.each do |method| +        expect( object ).to receive(method) +      end +      # Almost as powerful as Quicktest :P +      %i{xx xxx anything save!}.each do |method| +        subject.send method +      end +    end +  end + +  describe 'action links for' do + +    context 'unarchived referential' do +      context 'no rights' do +        it 'has only a Calendar action' do +          expect_action_link_hrefs.to eq([referential_time_tables_path(object)]) +        end +      end + +      context 'all rights and different organisation' do  + +        let( :user ){ build_stubbed :allmighty_user } + +        it 'has only default actions' do +          expect_action_link_elements.to be_empty +          expect_action_link_hrefs.to eq([ +            referential_time_tables_path(object), +          ]) +        end +      end +      context 'all rights and same organisation' do  + +        let( :user ){ build_stubbed :allmighty_user, organisation: referential.organisation } + +        it 'has all actions' do +          expect_action_link_elements.to eq(%w{Purger}) +          expect_action_link_hrefs.to eq([ +            referential_time_tables_path(object), +            new_referential_path(from: object), +            archive_referential_path(object), +            referential_path(object) +          ]) +        end +      end +    end + +    context 'archived referential' do +      before { referential.archived_at = 42.seconds.ago } +      context 'no rights' do +        it 'has only a Calendar action' do +          expect_action_link_hrefs.to eq([referential_time_tables_path(object)]) +        end +      end + +      context 'all rights and different organisation' do +        let( :user ){ build_stubbed :allmighty_user } +        it 'has only default actions' do +          expect_action_link_elements.to be_empty +          expect_action_link_hrefs.to eq([ +            referential_time_tables_path(object), +          ]) +        end +      end +    end +  end + + +end diff --git a/spec/policies/referential_policy_spec.rb b/spec/policies/referential_policy_spec.rb index d060317f9..33d8e13e8 100644 --- a/spec/policies/referential_policy_spec.rb +++ b/spec/policies/referential_policy_spec.rb @@ -56,22 +56,52 @@ RSpec.describe ReferentialPolicy, type: :policy do          add_permissions('referentials.update', for_user: user)        end -      it 'allowed for unarchived referentials' do -        expect_it.to permit(user_context, record) +      context 'same organisation →' do +        before do +          user.organisation_id = referential.organisation_id +        end +        it "allows a user with the same organisation" do +          expect_it.to permit(user_context, record) +        end +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'does remove permission for archived referentials' do +            expect_it.not_to permit(user_context, record) +          end +        end        end -      it 'forbidden for archived referentials' do -        record.archived_at = 1.second.ago -        expect_it.not_to permit(user_context, record) +      context 'different organisations →' do +        it "forbids a user with a different organisation" do +          expect_it.not_to permit(user_context, record) +        end + +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'forbids for archived referentials' do +            expect_it.not_to permit(user_context, record) +          end +        end +        end      end -    context 'permission absent →' do  -      it 'is forbidden' do -        expect_it.not_to permit(user_context, record) +    context 'permission absent →' do +      context 'same organisation →' do +        before do +          user.organisation_id = referential.organisation_id +        end +        it "forbids a user with the same organisation" do +          expect_it.not_to permit(user_context, record) +        end +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'forbids for archived referentials' do +            expect_it.not_to permit(user_context, record) +          end +        end        end      end -    end    permissions :unarchive? do @@ -81,22 +111,51 @@ RSpec.describe ReferentialPolicy, type: :policy do          add_permissions('referentials.update', for_user: user)        end -      it 'forbidden for unarchived referentials' do -        expect_it.not_to permit(user_context, record) +      context 'same organisation →' do +        before do +          user.organisation_id = referential.organisation_id +        end +        it "forbids a user with the same organisation" do +          expect_it.not_to permit(user_context, record) +        end +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'adds permission for archived referentials' do +            expect_it.to permit(user_context, record) +          end +        end        end -      it 'allowed for archived referentials' do -        record.archived_at = 1.second.ago -        expect_it.to permit(user_context, record) +      context 'different organisations →' do +        it "forbids a user with a different organisation" do +          expect_it.not_to permit(user_context, record) +        end + +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'still forbids for archived referentials' do +            expect_it.not_to permit(user_context, record) +          end +        end +        end      end -    context 'permission absent →' do  -      it 'is forbidden' do -        record.archived_at = 1.second.ago -        expect_it.not_to permit(user_context, record) +    context 'permission absent →' do +      context 'same organisation →' do +        before do +          user.organisation_id = referential.organisation_id +        end +        it "forbids a user with a different rganisation" do +          expect_it.not_to permit(user_context, record) +        end +        describe "archived" do +          let( :record ){ build_stubbed :referential, archived_at: 2.minutes.ago  } +          it 'still forbids for archived referentials' do +            expect_it.not_to permit(user_context, record) +          end +        end        end      end -    end  end diff --git a/spec/support/decorator_helpers.rb b/spec/support/decorator_helpers.rb new file mode 100644 index 000000000..4e1f1825f --- /dev/null +++ b/spec/support/decorator_helpers.rb @@ -0,0 +1,32 @@ +module Support +  def self.get_ivar(ivar_name) +    -> object do +      object.instance_variable_get("@#{ivar_name}") +    end +  end + +  module DecoratorHelpers +    def self.included(into) +      into.instance_eval do +        subject{ object.decorate } +        let( :policy ){ ::Pundit.policy(user_context, object) } +        let( :user_context ){ UserContext.new(user, referential: referential) } + +        before do +          allow_any_instance_of(Draper::HelperProxy).to receive(:policy).and_return policy +        end +      end +    end + +    def expect_action_link_hrefs +      expect( subject.action_links.select(&Link.method(:===)).map(&:href) ) +    end +    def expect_action_link_elements +      expect( subject.action_links.select(&HTMLElement.method(:===)).map(&Support.get_ivar(:content)) ) +    end +  end +end + +RSpec.configure do | c | +  c.include Support::DecoratorHelpers, type: :decorator +end | 
