diff --git a/app/components/admin/poll/questions/answers/documents/index_component.html.erb b/app/components/admin/poll/questions/answers/documents/index_component.html.erb index 9c6b95c20..9f34e68e9 100644 --- a/app/components/admin/poll/questions/answers/documents/index_component.html.erb +++ b/app/components/admin/poll/questions/answers/documents/index_component.html.erb @@ -8,15 +8,21 @@
- <%= form_for(Poll::Question::Answer.new, url: admin_answer_documents_path(answer)) do |f| %> - <%= render "shared/errors", resource: answer %> + <% if can?(:update, @answer) %> + <%= form_for(Poll::Question::Answer.new, url: admin_answer_documents_path(answer)) do |f| %> + <%= render "shared/errors", resource: answer %> -
- <%= render "documents/nested_documents", f: f %> -
+
+ <%= render "documents/nested_documents", f: f %> +
-
- <%= f.submit(class: "button expanded", value: t("shared.save")) %> +
+ <%= f.submit(class: "button expanded", value: t("shared.save")) %> +
+ <% end %> + <% else %> +
+ <%= t("admin.questions.no_edit") %>
<% end %> @@ -33,17 +39,7 @@ <%= link_to document.title, document.attachment %> - <%= render Admin::TableActionsComponent.new(document, - actions: [:destroy], - destroy_path: document_path(document) - ) do |actions| %> - <%= actions.action(:download, - text: t("documents.buttons.download_document"), - path: document.attachment, - target: "_blank", - rel: "nofollow") %> - - <% end %> + <%= render Admin::Poll::Questions::Answers::Documents::TableActionsComponent.new(document) %> <% end %> diff --git a/app/components/admin/poll/questions/answers/documents/index_component.rb b/app/components/admin/poll/questions/answers/documents/index_component.rb index ca72d4f98..5a46f05da 100644 --- a/app/components/admin/poll/questions/answers/documents/index_component.rb +++ b/app/components/admin/poll/questions/answers/documents/index_component.rb @@ -1,5 +1,6 @@ class Admin::Poll::Questions::Answers::Documents::IndexComponent < ApplicationComponent attr_reader :answer + delegate :can?, to: :helpers def initialize(answer) @answer = answer diff --git a/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb new file mode 100644 index 000000000..f2406512e --- /dev/null +++ b/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb @@ -0,0 +1,9 @@ +<%= render Admin::TableActionsComponent.new(document, + actions: actions, + destroy_path: document_path(document)) do |table_actions| %> + <%= table_actions.action(:download, + text: t("documents.buttons.download_document"), + path: document.attachment, + target: "_blank", + rel: "nofollow") %> +<% end %> diff --git a/app/components/admin/poll/questions/answers/documents/table_actions_component.rb b/app/components/admin/poll/questions/answers/documents/table_actions_component.rb new file mode 100644 index 000000000..38b7a7c08 --- /dev/null +++ b/app/components/admin/poll/questions/answers/documents/table_actions_component.rb @@ -0,0 +1,14 @@ +class Admin::Poll::Questions::Answers::Documents::TableActionsComponent < ApplicationComponent + attr_reader :document + delegate :can?, to: :helpers + + def initialize(document) + @document = document + end + + private + + def actions + [:destroy].select { |action| can?(action, document) } + end +end diff --git a/app/controllers/admin/poll/questions/answers/documents_controller.rb b/app/controllers/admin/poll/questions/answers/documents_controller.rb index 3210896d6..eeea65aa6 100644 --- a/app/controllers/admin/poll/questions/answers/documents_controller.rb +++ b/app/controllers/admin/poll/questions/answers/documents_controller.rb @@ -8,6 +8,7 @@ class Admin::Poll::Questions::Answers::DocumentsController < Admin::Poll::BaseCo def create @answer.attributes = documents_params + authorize! :update, @answer if @answer.save redirect_to admin_answer_documents_path(@answer), diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 3c94e802e..f6e2bb038 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -124,7 +124,9 @@ module Abilities cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal] can [:create], Document - can [:destroy], Document, documentable_type: "Poll::Question::Answer" + can [:destroy], Document do |document| + document.documentable_type == "Poll::Question::Answer" && can?(:update, document.documentable) + end can [:create, :destroy], DirectUpload can [:deliver], Newsletter, hidden_at: nil diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 264b98521..2da9a057d 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -71,7 +71,7 @@ module Abilities can [:create, :destroy], Follow, user_id: user.id can [:destroy], Document do |document| - document.documentable&.author_id == user.id + document.documentable_type != "Poll::Question::Answer" && document.documentable&.author_id == user.id end can [:destroy], Image do |image| diff --git a/spec/components/admin/poll/questions/answers/documents/index_component_spec.rb b/spec/components/admin/poll/questions/answers/documents/index_component_spec.rb new file mode 100644 index 000000000..053c37ce5 --- /dev/null +++ b/spec/components/admin/poll/questions/answers/documents/index_component_spec.rb @@ -0,0 +1,19 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::Documents::IndexComponent do + before { sign_in(create(:administrator).user) } + let(:future_answer) { create(:poll_question_answer, poll: create(:poll, :future)) } + let(:current_answer) { create(:poll_question_answer, poll: create(:poll)) } + + it "displays the 'Add new document' link when the poll has not started" do + render_inline Admin::Poll::Questions::Answers::Documents::IndexComponent.new(future_answer) + + expect(page).to have_link "Add new document" + end + + it "does not display the 'Add new document' link when the poll has started" do + render_inline Admin::Poll::Questions::Answers::Documents::IndexComponent.new(current_answer) + + expect(page).not_to have_link "Add new document" + end +end diff --git a/spec/components/admin/poll/questions/answers/documents/table_actions_component_spec.rb b/spec/components/admin/poll/questions/answers/documents/table_actions_component_spec.rb new file mode 100644 index 000000000..2d2261aea --- /dev/null +++ b/spec/components/admin/poll/questions/answers/documents/table_actions_component_spec.rb @@ -0,0 +1,27 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::Documents::TableActionsComponent, controller: Admin::BaseController do + before { sign_in(create(:administrator).user) } + let(:future_answer) { create(:poll_question_answer, poll: create(:poll, :future)) } + let(:current_answer) { create(:poll_question_answer, poll: create(:poll)) } + + it "displays the destroy action when the poll has not started" do + document = create(:document, documentable: future_answer) + + render_inline Admin::Poll::Questions::Answers::Documents::TableActionsComponent.new(document) + + expect(page).to have_link "Download file" + expect(page).to have_button "Delete" + expect(page).not_to have_link "Edit" + end + + it "does not display the destroy action when the poll has started" do + document = create(:document, documentable: current_answer) + + render_inline Admin::Poll::Questions::Answers::Documents::TableActionsComponent.new(document) + + expect(page).to have_link "Download file" + expect(page).not_to have_button "Delete" + expect(page).not_to have_link "Edit" + end +end diff --git a/spec/controllers/admin/poll/questions/answers/documents_controller_spec.rb b/spec/controllers/admin/poll/questions/answers/documents_controller_spec.rb new file mode 100644 index 000000000..84e02f0f6 --- /dev/null +++ b/spec/controllers/admin/poll/questions/answers/documents_controller_spec.rb @@ -0,0 +1,35 @@ +require "rails_helper" + +describe Admin::Poll::Questions::Answers::DocumentsController, :admin do + let(:current_answer) { create(:poll_question_answer, poll: create(:poll)) } + let(:future_answer) { create(:poll_question_answer, poll: create(:poll, :future)) } + + describe "POST create" do + let(:answer_attributes) do + { + documents_attributes: { + "0" => { + attachment: fixture_file_upload("clippy.pdf"), + title: "Title", + user_id: User.last.id + } + } + } + end + + it "is not possible for an already started poll" do + post :create, params: { poll_question_answer: answer_attributes, answer_id: current_answer } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'update' on Answer." + expect(Document.count).to eq 0 + end + + it "is possible for a not started poll" do + post :create, params: { poll_question_answer: answer_attributes, answer_id: future_answer } + + expect(response).to redirect_to admin_answer_documents_path(future_answer) + expect(flash[:notice]).to eq "Document uploaded successfully" + expect(Document.count).to eq 1 + end + end +end diff --git a/spec/controllers/documents_controller_spec.rb b/spec/controllers/documents_controller_spec.rb new file mode 100644 index 000000000..9b0977034 --- /dev/null +++ b/spec/controllers/documents_controller_spec.rb @@ -0,0 +1,28 @@ +require "rails_helper" + +describe DocumentsController do + describe "DELETE destroy" do + context "Poll answers administration", :admin do + let(:current_answer) { create(:poll_question_answer, poll: create(:poll)) } + let(:future_answer) { create(:poll_question_answer, poll: create(:poll, :future)) } + + it "is not possible for an already started poll" do + document = create(:document, documentable: current_answer) + delete :destroy, params: { id: document } + + expect(flash[:alert]).to eq "You do not have permission to carry out the action 'destroy' on Document." + expect(Document.count).to eq 1 + end + + it "is possible for a not started poll" do + document = create(:document, documentable: future_answer) + request.env["HTTP_REFERER"] = admin_answer_documents_path(future_answer) + delete :destroy, params: { id: document } + + expect(response).to redirect_to admin_answer_documents_path(future_answer) + expect(flash[:notice]).to eq "Document was deleted successfully." + expect(Document.count).to eq 0 + end + end + end +end diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index 2eebf28a1..4579aa4c8 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -26,6 +26,8 @@ describe Abilities::Administrator do let(:future_poll_answer_video) { create(:poll_answer_video, answer: future_poll_question_answer) } let(:current_poll_answer_image) { build(:image, imageable: current_poll_question_answer) } let(:future_poll_answer_image) { build(:image, imageable: future_poll_question_answer) } + let(:current_poll_answer_document) { build(:document, documentable: current_poll_question_answer) } + let(:future_poll_answer_document) { build(:document, documentable: future_poll_question_answer) } let(:past_process) { create(:legislation_process, :past) } let(:past_draft_process) { create(:legislation_process, :past, :not_published) } @@ -145,6 +147,9 @@ describe Abilities::Administrator do it { should be_able_to(:destroy, future_poll_answer_image) } it { should_not be_able_to(:destroy, current_poll_answer_image) } + it { should be_able_to(:destroy, future_poll_answer_document) } + it { should_not be_able_to(:destroy, current_poll_answer_document) } + it { is_expected.to be_able_to :manage, Dashboard::AdministratorTask } it { is_expected.to be_able_to :manage, dashboard_administrator_task } diff --git a/spec/system/admin/poll/questions/answers/documents/documents_spec.rb b/spec/system/admin/poll/questions/answers/documents/documents_spec.rb index 8a3b3e356..d4439e5bb 100644 --- a/spec/system/admin/poll/questions/answers/documents/documents_spec.rb +++ b/spec/system/admin/poll/questions/answers/documents/documents_spec.rb @@ -1,6 +1,8 @@ require "rails_helper" describe "Documents", :admin do + let(:future_poll) { create(:poll, :future) } + context "Index" do scenario "Answer with no documents" do answer = create(:poll_question_answer) @@ -23,7 +25,7 @@ describe "Documents", :admin do end scenario "Create document for answer" do - answer = create(:poll_question_answer) + answer = create(:poll_question_answer, poll: future_poll) visit admin_answer_documents_path(answer) @@ -35,7 +37,7 @@ describe "Documents", :admin do end scenario "Remove document from answer" do - answer = create(:poll_question_answer) + answer = create(:poll_question_answer, poll: future_poll) document = create(:document, documentable: answer) visit admin_answer_documents_path(answer) @@ -45,6 +47,7 @@ describe "Documents", :admin do click_button "Delete" end + expect(page).to have_content "Document was deleted successfully." expect(page).not_to have_content(document.title) end end