diff --git a/decidim-assemblies/app/views/decidim/assemblies/assemblies/show.html.erb b/decidim-assemblies/app/views/decidim/assemblies/assemblies/show.html.erb index 5bef8f269688b..b64461ad2d923 100644 --- a/decidim-assemblies/app/views/decidim/assemblies/assemblies/show.html.erb +++ b/decidim-assemblies/app/views/decidim/assemblies/assemblies/show.html.erb @@ -37,7 +37,7 @@ edit_link(
` tag and include the badge right after it. This # makes the layout look good. def description - text = super - text.sub!(/
/, "
#{render :badge}") - html_truncate(text, length: 100) + render(:badge) + truncate(strip_tags(super), length: 100) end def resource_path diff --git a/decidim-consultations/app/scrubbers/decidim/consultations/question_title_scrubber.rb b/decidim-consultations/app/scrubbers/decidim/consultations/question_title_scrubber.rb new file mode 100644 index 0000000000000..6d4f6742eb220 --- /dev/null +++ b/decidim-consultations/app/scrubbers/decidim/consultations/question_title_scrubber.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Decidim + module Consultations + class QuestionTitleScrubber < Decidim::UserInputScrubber + private + + def custom_allowed_tags + %w(strong em u b i br ul ol li p a code) + end + + def custom_allowed_attributes + %w(class href target rel) + end + end + end +end diff --git a/decidim-consultations/app/views/decidim/consultations/consultations/_consultation_details.html.erb b/decidim-consultations/app/views/decidim/consultations/consultations/_consultation_details.html.erb index ac198c7b4477b..fd08af9db5ab9 100644 --- a/decidim-consultations/app/views/decidim/consultations/consultations/_consultation_details.html.erb +++ b/decidim-consultations/app/views/decidim/consultations/consultations/_consultation_details.html.erb @@ -1,6 +1,6 @@
<%= decidim_sanitize_editor translated_attribute(consultation.description) %>
+<%= decidim_sanitize_editor_admin translated_attribute(consultation.description) %>
<%= translated_attribute question.subtitle %>
<%= t "questions.vote_modal.contextual_help", scope: "decidim" %>
<%= decidim_sanitize_editor translated_attribute(current_question.what_is_decided), strip_tags: true %>
+<%= decidim_sanitize_editor_admin translated_attribute(current_question.what_is_decided) %>
<%= decidim_sanitize_editor translated_attribute(current_question.question_context), strip_tags: true %>
+<%= decidim_sanitize_editor_admin translated_attribute(current_question.question_context) %>
Hello,
" + expect(html).to be_scrubbed_as("Hello,
") + end + + it "does not allow disabled iframes" do + html = %() + expect(html).to be_scrubbed_as("") + end + + it "allows most basic tags" do + html = "", "
") { generate_localized_title } } + let(:what_is_decided) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_title } } let(:previous_question) { create :question, consultation: consultation } - let(:question) { create :question, consultation: consultation } + let(:question) { create :question, consultation: consultation, question_context: question_context, what_is_decided: what_is_decided } let(:next_question) { create :question, consultation: consultation } context "when shows question information" do @@ -15,6 +17,18 @@ visit decidim_consultations.question_path(question) end + context "when displaying question context" do + it_behaves_like "has embedded video in description", :question_context, count: 2 do + before { click_button("Read more") } + end + end + + context "when displaying what is decided" do + it_behaves_like "has embedded video in description", :what_is_decided do + before { click_button("Read more") } + end + end + it "Shows the basic question data" do expect(page).to have_i18n_content(question.promoter_group) expect(page).to have_i18n_content(question.scope.name) diff --git a/decidim-core/app/scrubbers/decidim/admin_input_scrubber.rb b/decidim-core/app/scrubbers/decidim/admin_input_scrubber.rb index 13ad3b49ef1f0..e45d930204fce 100644 --- a/decidim-core/app/scrubbers/decidim/admin_input_scrubber.rb +++ b/decidim-core/app/scrubbers/decidim/admin_input_scrubber.rb @@ -14,12 +14,14 @@ module Decidim class AdminInputScrubber < UserInputScrubber private + DECIDIM_ALLOWED_TAGS = %w(img video audio source comment iframe).freeze + def custom_allowed_attributes super + %w(frameborder allowfullscreen) - %w(onerror) end def custom_allowed_tags - super + %w(comment iframe) + super + DECIDIM_ALLOWED_TAGS end end end diff --git a/decidim-core/app/scrubbers/decidim/user_input_scrubber.rb b/decidim-core/app/scrubbers/decidim/user_input_scrubber.rb index c32321d41dce5..2626dd260969c 100644 --- a/decidim-core/app/scrubbers/decidim/user_input_scrubber.rb +++ b/decidim-core/app/scrubbers/decidim/user_input_scrubber.rb @@ -18,12 +18,41 @@ def initialize private + RESTRICTED_TAGS = %w( + area + article + aside + audio + button + canvas + fieldset + figcaption + figure + font + footer + form + header + img + input + label + legend + main + map + menu + optgroup + option + output + select + textarea + video + ).freeze + def custom_allowed_attributes Loofah::HTML5::SafeList::ALLOWED_ATTRIBUTES end def custom_allowed_tags - Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2 + Loofah::HTML5::SafeList::ACCEPTABLE_ELEMENTS - RESTRICTED_TAGS end end end diff --git a/decidim-core/lib/decidim/core/test/shared_examples/editor_shared_examples.rb b/decidim-core/lib/decidim/core/test/shared_examples/editor_shared_examples.rb index e54c4490f3747..8bcc720b91309 100644 --- a/decidim-core/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +++ b/decidim-core/lib/decidim/core/test/shared_examples/editor_shared_examples.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -shared_examples_for "has embedded video in description" do |description_attribute_name| +shared_examples_for "has embedded video in description" do |description_attribute_name, count: 1| let(description_attribute_name) { { en: %(Description ) } } let(:iframe_src) { "http://www.example.org" } + let!(:cookie_warning) { "You need to enable all cookies in order to see this content" } context "when cookies are rejected" do before do @@ -11,7 +12,7 @@ end it "disables iframe" do - expect(page).to have_content("You need to enable all cookies in order to see this content") + expect(page).to have_content(cookie_warning) expect(page).not_to have_selector("iframe") end end @@ -23,8 +24,8 @@ end it "shows iframe" do - expect(page).not_to have_content("You need to enable all cookies in order to see this content") - expect(page).to have_selector("iframe", count: 1) + expect(page).not_to have_content(cookie_warning) + expect(page).to have_selector("iframe", count: count) end end end diff --git a/decidim-core/spec/scrubbers/decidim/user_input_scrubber_spec.rb b/decidim-core/spec/scrubbers/decidim/user_input_scrubber_spec.rb index 5e0ec0371f130..8efd76ef78154 100644 --- a/decidim-core/spec/scrubbers/decidim/user_input_scrubber_spec.rb +++ b/decidim-core/spec/scrubbers/decidim/user_input_scrubber_spec.rb @@ -56,6 +56,6 @@ def scrub(html) it "does not allow onerror attributes" do html = "", "
") { generate_localized_debate_title } } + let(:information_updates) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_debate_title } } + let(:instructions) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_debate_title } } + let!(:debate) { create(:debate, component: component, description: description, information_updates: information_updates, instructions: instructions, skip_injection: true) } before do visit_component click_link debate.title[I18n.locale.to_s], class: "card__link" end + context "when is created from the admin panel" do + let!(:debate) { create(:debate, :official, component: component, description: description, information_updates: information_updates, instructions: instructions) } + + context "when the field is decription" do + it_behaves_like "has embedded video in description", :description + end + + context "when the field is information_updates" do + it_behaves_like "has embedded video in description", :information_updates + end + + context "when the field is instructions" do + it_behaves_like "has embedded video in description", :instructions + end + end + + context "when is created by the participant" do + let!(:debate) { create(:debate, :participant_author, component: component, description: description, information_updates: information_updates, instructions: instructions) } + let(:iframe_src) { "http://www.example.org" } + + context "when the field is decription" do + let(:description) { { en: %(Description ) } } + + it { expect(page).not_to have_selector("iframe") } + end + + context "when the field is information_updates" do + let(:information_updates) { { en: %(Description ) } } + + it { expect(page).not_to have_selector("iframe") } + end + + context "when the field is instructions" do + let(:instructions) { { en: %(Description ) } } + + it { expect(page).not_to have_selector("iframe") } + end + end + context "when shows the debate component" do it "shows the debate title" do expect(page).to have_content debate.title[I18n.locale.to_s] diff --git a/decidim-elections/app/views/decidim/elections/elections/show.html.erb b/decidim-elections/app/views/decidim/elections/elections/show.html.erb index 23b93809f6ecc..03525425c509d 100644 --- a/decidim-elections/app/views/decidim/elections/elections/show.html.erb +++ b/decidim-elections/app/views/decidim/elections/elections/show.html.erb @@ -45,7 +45,7 @@ edit_link( <% end %><%= decidim_sanitize_editor(simple_format(translated_attribute(election.description)), strip_tags: true) %>
+<%= decidim_sanitize_editor_admin(translated_attribute(election.description)) %>
<%= cell("decidim/elections/election_vote_cta", election) %> diff --git a/decidim-elections/spec/system/explore_elections_spec.rb b/decidim-elections/spec/system/explore_elections_spec.rb index bf192b54d7aac..455fe45249015 100644 --- a/decidim-elections/spec/system/explore_elections_spec.rb +++ b/decidim-elections/spec/system/explore_elections_spec.rb @@ -136,7 +136,8 @@ describe "show" do let(:elections_count) { 1 } - let(:election) { elections.first } + let(:description) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_title } } + let(:election) { create(:election, :complete, :published, :ongoing, component: component, description: description) } let(:question) { election.questions.first } let(:image) { create(:attachment, :with_image, attached_to: election) } @@ -145,6 +146,8 @@ visit resource_locator(election).path end + it_behaves_like "has embedded video in description", :description + it "shows all election info" do expect(page).to have_i18n_content(election.title) expect(page).to have_i18n_content(election.description) diff --git a/decidim-forms/app/views/decidim/forms/questionnaires/_answer.html.erb b/decidim-forms/app/views/decidim/forms/questionnaires/_answer.html.erb index 8149b202bdbe5..b1d4042e71da3 100644 --- a/decidim-forms/app/views/decidim/forms/questionnaires/_answer.html.erb +++ b/decidim-forms/app/views/decidim/forms/questionnaires/_answer.html.erb @@ -7,7 +7,7 @@ <%= label_tag field_id, translated_attribute(answer.question.body), class: "questionnaire-title_and_description" %> <% if translated_attribute(answer.question.description).present? %>` tag and include the badge right after it. This # makes the layout look good. def description - text = decidim_sanitize_editor(translated_attribute(model.additional_info)) + text = decidim_sanitize_editor(translated_attribute(model.additional_info), strip_tags: true) text.sub!(/
/, "
#{render :badge}") html_truncate(text, length: 100) end diff --git a/decidim-sortitions/app/views/decidim/sortitions/sortitions/show.html.erb b/decidim-sortitions/app/views/decidim/sortitions/sortitions/show.html.erb index b45a27eebeea1..0774dbddf1e47 100644 --- a/decidim-sortitions/app/views/decidim/sortitions/sortitions/show.html.erb +++ b/decidim-sortitions/app/views/decidim/sortitions/sortitions/show.html.erb @@ -39,7 +39,7 @@
", "
") { generate_localized_title } } + let(:additional_info) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_title } } + let(:cancel_reason) { Decidim::Faker::Localized.wrapped("", "
") { generate_localized_title } } + let!(:sortition) { create(:sortition, :cancelled, component: component, witnesses: witnesses, additional_info: additional_info, cancel_reason: cancel_reason) } before do page.visit "#{main_component_path(component)}?filter[with_any_state]=cancelled" click_link "View" end + context "when the field is additional_info" do + it_behaves_like "has embedded video in description", :additional_info + end + it "shows the cancel reasons" do expect(page).to have_content(sortition.cancel_reason[:en]) end diff --git a/decidim-surveys/spec/system/survey_spec.rb b/decidim-surveys/spec/system/survey_spec.rb index 16b97daa5ac27..66db4beeb5a86 100644 --- a/decidim-surveys/spec/system/survey_spec.rb +++ b/decidim-surveys/spec/system/survey_spec.rb @@ -19,10 +19,17 @@ "es" => "Contenido de la encuesta
" } end + let(:question_description) do + { + "en" => "Survey's content
", + "ca" => "Contingut de l'enquesta
", + "es" => "Contenido de la encuesta
" + } + end let(:user) { create(:user, :confirmed, organization: component.organization) } let!(:questionnaire) { create(:questionnaire, title: title, description: description) } let!(:survey) { create(:survey, component: component, questionnaire: questionnaire) } - let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, position: 0) } + let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, position: 0, description: question_description) } include_context "with a component" @@ -92,6 +99,29 @@ it_behaves_like "has questionnaire" end + + context "when displaying questionnaire rich content" do + before do + component.update!( + step_settings: { + component.participatory_space.active_step.id => { + allow_answers: true, + allow_unregistered: true + } + }, + settings: { starts_at: 1.week.ago, ends_at: 1.day.from_now } + ) + visit_component + end + + context "when displaying questionnaire description" do + it_behaves_like "has embedded video in description", :description + end + + context "when displaying question description" do + it_behaves_like "has embedded video in description", :question_description + end + end end context "when survey has action log entry" do