diff --git a/app/models/contract.rb b/app/models/contract.rb index 534c264..1c475e3 100644 --- a/app/models/contract.rb +++ b/app/models/contract.rb @@ -29,6 +29,10 @@ class Contract } end + def medical_release? + @releasable.instance_of?(MedicalRelease) + end + private def contract_template diff --git a/app/policies/contract_policy.rb b/app/policies/contract_policy.rb index c6a9b9e..f904cc5 100644 --- a/app/policies/contract_policy.rb +++ b/app/policies/contract_policy.rb @@ -1,5 +1,9 @@ class ContractPolicy < ApplicationPolicy def show? - user.manager? || user.account_manager? + if record.respond_to?(:medical_release?) && record.medical_release? + user.account_manager? + else + user.manager? || user.account_manager? + end end end diff --git a/app/policies/medical_release_policy.rb b/app/policies/medical_release_policy.rb index 126f992..b752a8b 100644 --- a/app/policies/medical_release_policy.rb +++ b/app/policies/medical_release_policy.rb @@ -4,7 +4,7 @@ class MedicalReleasePolicy < ReleasePolicy end def show? - true + user.account_manager? end def update? @@ -31,7 +31,11 @@ class MedicalReleasePolicy < ReleasePolicy true end + def download_single? + user.account_manager? + end + def download_multiple? - true + download_single? end end diff --git a/app/views/medical_releases/_medical_release.html.erb b/app/views/medical_releases/_medical_release.html.erb index 2b813e4..29c4b73 100644 --- a/app/views/medical_releases/_medical_release.html.erb +++ b/app/views/medical_releases/_medical_release.html.erb @@ -37,7 +37,7 @@ <% if policy(medical_release.tags).new? %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, medical_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <% end %> - <% if policy(Contract).show? && (medical_release.contract.attached? || medical_release.contract_template.present?) %> + <% if policy(MedicalRelease).download_single? && policy(Contract).show? && (medical_release.contract.attached? || medical_release.contract_template.present?) %> <%= link_to fa_icon("download fw", text: "Download"), [medical_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <% end %> <% if policy(medical_release).destroy? %> diff --git a/spec/controllers/contracts_controller_spec.rb b/spec/controllers/contracts_controller_spec.rb index 5456dcf..6d6976a 100644 --- a/spec/controllers/contracts_controller_spec.rb +++ b/spec/controllers/contracts_controller_spec.rb @@ -63,4 +63,55 @@ RSpec.describe ContractsController, type: :controller do it_behaves_like "a contracts controller" end + + context "for medical releases" do + let(:native_releasable) { create(:medical_release_with_contract_template, :native) } + let(:non_native_releasable) { create(:medical_release_with_contract_template, :non_native) } + + describe "#show when user is account manager" do + it_behaves_like "a contracts controller" + end + + shared_examples "a medical contracts controller for non-authorized users" do + describe "#show" do + context "for a native release" do + it "responds with not authorized error" do + pdf_body = Tempfile.new + allow_any_instance_of(Contract).to receive(:to_pdf).and_return(pdf_body) + + expect { + get :show, params: { format: :pdf, "#{native_releasable.model_name.singular}_id" => native_releasable } + }.to raise_exception(Pundit::NotAuthorizedError) + end + end + + context "for a non-native release" do + it "responds with the attached contract" do + contract = double(:contract, service_url: "http://example.org/contract.pdf") + allow_any_instance_of(non_native_releasable.class).to receive(:contract).and_return(contract) + + expect { + get :show, params: { format: :pdf, "#{non_native_releasable.model_name.singular}_id" => non_native_releasable } + }.to raise_exception(Pundit::NotAuthorizedError) + end + end + end + end + + describe "#show when user is project manager" do + let(:manager_user) { create(:user, :manager) } + before do + sign_in manager_user + end + it_behaves_like "a medical contracts controller for non-authorized users" + end + + describe "#show when user is associate" do + let(:associate_user) { create(:user, :associate) } + before do + sign_in associate_user + end + it_behaves_like "a medical contracts controller for non-authorized users" + end + end end diff --git a/spec/features/user_managing_medical_releases_spec.rb b/spec/features/user_managing_medical_releases_spec.rb new file mode 100644 index 0000000..a42a1d6 --- /dev/null +++ b/spec/features/user_managing_medical_releases_spec.rb @@ -0,0 +1,145 @@ +require "rails_helper" + +feature "User managing medical releases" do + let(:current_user) { create(:user) } + let(:project) { create(:project, members: current_user, account: current_user.primary_account) } + + context "when signed in as account manager" do + before do + sign_in current_user + end + + scenario "Download All is visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).to have_content download_all_button + end + + scenario "Download action in Manage menu is visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).to have_link("Download", exact: true, count: 2) + end + + scenario "Downloading PDF of native medical release is possible" do + native_release = create(:medical_release_with_contract_template, :native, project: project) + + visit project_medical_releases_path(project) + + click_link *view_release_pdf_link_for(native_release) + expect(content_type).to eq('application/pdf') + end + end + + context "when the user is manager(project manager)" do + let(:current_user) { create(:user, :manager) } + + before do + sign_in current_user + end + + scenario "Download All is not visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).not_to have_content download_all_button + end + + scenario "Download action in Manage menu is not visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).to have_link("Download", exact: true, count: 0) + end + + scenario "Downloading PDF of native medical release is not possible" do + native_release = create(:medical_release_with_contract_template, :native, project: project) + + visit project_medical_releases_path(project) + + link = medical_release_contracts_path(native_release, format: 'pdf') + expect { visit link }.to raise_exception Pundit::NotAuthorizedError + end + + scenario "Downloading PDF of non native medical release is not possible" do + non_native_release = create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + link = medical_release_contracts_path(non_native_release, format: 'pdf') + expect { visit link }.to raise_exception Pundit::NotAuthorizedError + end + end + + context "when the user is associate" do + let(:current_user) { create(:user, :associate) } + + before do + sign_in current_user + end + + scenario "Download All is not visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).not_to have_content download_all_button + end + + scenario "Download action in Manage menu is not visible" do + create(:medical_release_with_contract_template, :native, project: project) + create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + expect(page).to have_link("Download", exact: true, count: 0) + end + + scenario "Downloading PDF of native medical release is not possible" do + native_release = create(:medical_release_with_contract_template, :native, project: project) + + visit project_medical_releases_path(project) + + link = medical_release_contracts_path(native_release, format: 'pdf') + expect { visit link }.to raise_exception Pundit::NotAuthorizedError + end + + scenario "Downloading PDF of non native medical release is not possible" do + non_native_release = create(:medical_release_with_contract_template, :non_native, project: project) + + visit project_medical_releases_path(project) + + link = medical_release_contracts_path(non_native_release, format: 'pdf') + expect { visit link }.to raise_exception Pundit::NotAuthorizedError + end + end + + private + + def download_all_button + 'Download All' + end + + def download_action + 'Download' + end + + def manage_button + t 'medical_releases.medical_release.actions.manage' + end + + def view_release_pdf_link_for(release) + ['Download', href: medical_release_contracts_path(release, format: 'pdf')] + end +end diff --git a/spec/policies/medical_release_policy_spec.rb b/spec/policies/medical_release_policy_spec.rb index 8b79891..b4b7421 100644 --- a/spec/policies/medical_release_policy_spec.rb +++ b/spec/policies/medical_release_policy_spec.rb @@ -1,7 +1,8 @@ require "rails_helper" describe MedicalReleasePolicy do - let(:user_context) { build(:user_context) } + let(:user) { create(:user) } + let(:user_context) { create(:user_context, user: user, account: user.primary_account) } subject { described_class } @@ -9,8 +10,28 @@ describe MedicalReleasePolicy do it { is_expected.to permit(:create) } end - permissions :show? do - it { is_expected.to permit(:show) } + context "for an account manager" do + let(:user) { create(:user, :account_manager) } + + permissions :show? do + it { is_expected.to permit(user_context, :show) } + end + end + + context "for an associate" do + let(:user) { create(:user, :associate) } + + permissions :show? do + it { is_expected.not_to permit(user_context, :show) } + end + end + + context "for a manager" do + let(:user) { create(:user, :manager) } + + permissions :show? do + it { is_expected.not_to permit(user_context, :show) } + end end permissions :update? do