Don't allow to modify answer's documents for started polls

This commit is contained in:
Julian Herrero
2022-09-05 11:33:13 +02:00
committed by Javi Martín
parent 245594f32b
commit 4c8f247de7
13 changed files with 162 additions and 22 deletions

View File

@@ -8,15 +8,21 @@
</ul> </ul>
<div class="poll-question-form"> <div class="poll-question-form">
<%= form_for(Poll::Question::Answer.new, url: admin_answer_documents_path(answer)) do |f| %> <% if can?(:update, @answer) %>
<%= render "shared/errors", resource: answer %> <%= form_for(Poll::Question::Answer.new, url: admin_answer_documents_path(answer)) do |f| %>
<%= render "shared/errors", resource: answer %>
<div class="documents"> <div class="documents">
<%= render "documents/nested_documents", f: f %> <%= render "documents/nested_documents", f: f %>
</div> </div>
<div class="small-12 medium-6 large-2"> <div class="small-12 medium-6 large-2">
<%= f.submit(class: "button expanded", value: t("shared.save")) %> <%= f.submit(class: "button expanded", value: t("shared.save")) %>
</div>
<% end %>
<% else %>
<div class="callout warning">
<strong><%= t("admin.questions.no_edit") %></strong>
</div> </div>
<% end %> <% end %>
@@ -33,17 +39,7 @@
<%= link_to document.title, document.attachment %> <%= link_to document.title, document.attachment %>
</td> </td>
<td> <td>
<%= render Admin::TableActionsComponent.new(document, <%= render Admin::Poll::Questions::Answers::Documents::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 %>
</td> </td>
</tr> </tr>
<% end %> <% end %>

View File

@@ -1,5 +1,6 @@
class Admin::Poll::Questions::Answers::Documents::IndexComponent < ApplicationComponent class Admin::Poll::Questions::Answers::Documents::IndexComponent < ApplicationComponent
attr_reader :answer attr_reader :answer
delegate :can?, to: :helpers
def initialize(answer) def initialize(answer)
@answer = answer @answer = answer

View File

@@ -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 %>

View File

@@ -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

View File

@@ -8,6 +8,7 @@ class Admin::Poll::Questions::Answers::DocumentsController < Admin::Poll::BaseCo
def create def create
@answer.attributes = documents_params @answer.attributes = documents_params
authorize! :update, @answer
if @answer.save if @answer.save
redirect_to admin_answer_documents_path(@answer), redirect_to admin_answer_documents_path(@answer),

View File

@@ -124,7 +124,9 @@ module Abilities
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal] cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal]
can [:create], Document 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 [:create, :destroy], DirectUpload
can [:deliver], Newsletter, hidden_at: nil can [:deliver], Newsletter, hidden_at: nil

View File

@@ -71,7 +71,7 @@ module Abilities
can [:create, :destroy], Follow, user_id: user.id can [:create, :destroy], Follow, user_id: user.id
can [:destroy], Document do |document| can [:destroy], Document do |document|
document.documentable&.author_id == user.id document.documentable_type != "Poll::Question::Answer" && document.documentable&.author_id == user.id
end end
can [:destroy], Image do |image| can [:destroy], Image do |image|

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -26,6 +26,8 @@ describe Abilities::Administrator do
let(:future_poll_answer_video) { create(:poll_answer_video, answer: future_poll_question_answer) } 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(:current_poll_answer_image) { build(:image, imageable: current_poll_question_answer) }
let(:future_poll_answer_image) { build(:image, imageable: future_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_process) { create(:legislation_process, :past) }
let(:past_draft_process) { create(:legislation_process, :past, :not_published) } 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 be_able_to(:destroy, future_poll_answer_image) }
it { should_not be_able_to(:destroy, current_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::AdministratorTask }
it { is_expected.to be_able_to :manage, dashboard_administrator_task } it { is_expected.to be_able_to :manage, dashboard_administrator_task }

View File

@@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
describe "Documents", :admin do describe "Documents", :admin do
let(:future_poll) { create(:poll, :future) }
context "Index" do context "Index" do
scenario "Answer with no documents" do scenario "Answer with no documents" do
answer = create(:poll_question_answer) answer = create(:poll_question_answer)
@@ -23,7 +25,7 @@ describe "Documents", :admin do
end end
scenario "Create document for answer" do 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) visit admin_answer_documents_path(answer)
@@ -35,7 +37,7 @@ describe "Documents", :admin do
end end
scenario "Remove document from answer" do scenario "Remove document from answer" do
answer = create(:poll_question_answer) answer = create(:poll_question_answer, poll: future_poll)
document = create(:document, documentable: answer) document = create(:document, documentable: answer)
visit admin_answer_documents_path(answer) visit admin_answer_documents_path(answer)
@@ -45,6 +47,7 @@ describe "Documents", :admin do
click_button "Delete" click_button "Delete"
end end
expect(page).to have_content "Document was deleted successfully."
expect(page).not_to have_content(document.title) expect(page).not_to have_content(document.title)
end end
end end