Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
env:
RUBY_VERSION: 3.2.6
NODE_VERSION: 18.17.1
NODE_OPTIONS: "--experimental-global-webcrypto"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about this? what is it?

DISABLE_SPRING: 1
CI: "true"

Expand Down Expand Up @@ -39,7 +40,7 @@ jobs:
fetch-depth: 1

- name: Install imagemagick and wkhtmltopdf
run: sudo apt install imagemagick wkhtmltopdf
run: sudo apt-get update && sudo apt-get install -y imagemagick wkhtmltopdf

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
run: sudo apt-get update && sudo apt-get install -y imagemagick wkhtmltopdf
run: sudo apt-get update && sudo apt-get install -y imagemagick libu2f-udev

We don't need that anymore right?


- uses: ruby/setup-ruby@v1
with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,29 @@ def box_color_as_hsla(document, opacity: 0.95)
"hsla(#{h}, #{s}%, 90%, #{opacity})"
end

# The PDF is fetched by pdf.js through an ActiveStorage redirect, so when
# the file lives in a remote storage service (S3 and compatible) the
# final blob host must be allowed by the connect-src CSP directive.
def append_storage_host_to_csp
origin = pdf_storage_origin
content_security_policy.append_csp_directive("connect-src", origin) if origin
end

def pdf_storage_origin
return if document.blank? || !document.file.attached?

ActiveStorage::Current.url_options ||= { host: request.base_url }
Comment thread
antopalidi marked this conversation as resolved.
uri = URI.parse(document.file.blob.url)
return if uri.host.blank?
return if uri.host == request.host && uri.port == request.port

origin = "#{uri.scheme}://#{uri.host}"
origin += ":#{uri.port}" if uri.port != uri.default_port
origin
rescue StandardError
nil
end

def pdf_custom_style
return if document.blank?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class DocumentsController < Admin::ApplicationController
redirect_to(documents_path) if document.blank?
end

before_action :append_storage_host_to_csp, only: [:pdf_viewer, :edit_pdf]

def index
redirect_to(document_suggestions_path(document)) && return if document.present? && document.file.attached?
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module ParticipatoryDocuments
class DocumentsController < Decidim::ParticipatoryDocuments::ApplicationController
helper Decidim::LayoutHelper

before_action :append_storage_host_to_csp, only: [:pdf_viewer]

def pdf_viewer
render layout: false
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require "spec_helper"

module Decidim
module ParticipatoryDocuments
module Admin
describe DocumentsController do
routes { Decidim::ParticipatoryDocuments::AdminEngine.routes }

let(:organization) { component.organization }
let(:participatory_process) { component.participatory_space }
let(:component) { document.component }
let(:document) { create(:participatory_documents_document, :with_file) }
let(:user) { create(:user, :admin, :confirmed, organization:) }

before do
request.env["decidim.current_organization"] = organization
request.env["decidim.current_participatory_space"] = participatory_process
request.env["decidim.current_component"] = component
sign_in user
end

describe "GET pdf_viewer" do
context "when the file is stored in a remote service" do
let(:remote_url) { "https://eu2.contabostorage.com/bucket/file.pdf?X-Amz-Signature=abc" }

before do
allow(ActiveStorage::Blob.service).to receive(:url).and_return(remote_url)
end

it "appends the storage host to the connect-src CSP directive" do
get :pdf_viewer
expect(response.headers["Content-Security-Policy"]).to match(%r{connect-src [^;]*https://eu2\.contabostorage\.com})
end
end
end
Comment thread
antopalidi marked this conversation as resolved.

describe "GET edit_pdf" do
context "when the file is stored in a remote service" do
let(:remote_url) { "https://eu2.contabostorage.com/bucket/file.pdf?X-Amz-Signature=abc" }

before do
allow(ActiveStorage::Blob.service).to receive(:url).and_return(remote_url)
end

it "appends the storage host to the connect-src CSP directive" do
get :edit_pdf
expect(response.headers["Content-Security-Policy"]).to match(%r{connect-src [^;]*https://eu2\.contabostorage\.com})
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

require "spec_helper"

module Decidim
module ParticipatoryDocuments
describe DocumentsController do
routes { Decidim::ParticipatoryDocuments::Engine.routes }

let(:organization) { component.organization }
let(:participatory_process) { component.participatory_space }
let(:component) { document.component }
let(:document) { create(:participatory_documents_document, :with_file) }

before do
request.env["decidim.current_organization"] = organization
request.env["decidim.current_participatory_space"] = participatory_process
request.env["decidim.current_component"] = component
end

describe "GET pdf_viewer" do
it "renders the pdf_viewer template" do
get :pdf_viewer
expect(response).to render_template("pdf_viewer")
end

context "when the file is stored in a remote service" do
let(:remote_url) { "https://eu2.contabostorage.com/bucket/file.pdf?X-Amz-Signature=abc" }

before do
allow(ActiveStorage::Blob.service).to receive(:url).and_return(remote_url)
end

it "appends the storage host to the connect-src CSP directive" do
get :pdf_viewer
expect(response.headers["Content-Security-Policy"]).to match(%r{connect-src [^;]*https://eu2\.contabostorage\.com})
end
end

context "when the file is stored in the local service" do
it "does not append the request host to the connect-src CSP directive" do
get :pdf_viewer
csp = response.headers["Content-Security-Policy"]
expect(csp).to match(/connect-src [^;]*'self'/)
expect(csp[/connect-src [^;]*/]).not_to include("test.host")
end
end

context "when the document has no file attached" do
let(:document) { create(:participatory_documents_document) }

it "renders without altering the connect-src CSP directive" do
get :pdf_viewer
expect(response.headers["Content-Security-Policy"][/connect-src [^;]*/]).not_to include("test.host")
end
end
end
end
end
end
Loading