diff --git a/config/dev.exs b/config/dev.exs index 781d0ee2..674709ff 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -72,6 +72,12 @@ config :philomena, PhilomenaWeb.Endpoint, ] ] +# Relax CSP rules in development +config :philomena, csp_relaxed: true + +# Enable Vite HMR +config :philomena, vite_reload: true + # Do not include metadata nor timestamps in development logs config :logger, :console, format: "[$level] $message\n" diff --git a/config/runtime.exs b/config/runtime.exs index b7a71c3e..9cd91ed5 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -134,22 +134,10 @@ if config_env() == :prod do url: [host: System.fetch_env!("APP_HOSTNAME"), scheme: "https", port: 443], secret_key_base: System.fetch_env!("SECRET_KEY_BASE"), server: not is_nil(System.get_env("START_ENDPOINT")) - - # Do not relax CSP in production - config :philomena, csp_relaxed: false - - # Disable Vite HMR in prod - config :philomena, vite_reload: false else # Don't send email in development config :philomena, Philomena.Mailer, adapter: Bamboo.LocalAdapter # Use this to debug slime templates # config :slime, :keep_lines, true - - # Relax CSP rules in development and test servers - config :philomena, csp_relaxed: true - - # Enable Vite HMR - config :philomena, vite_reload: true end diff --git a/lib/philomena_web/config.ex b/lib/philomena_web/config.ex new file mode 100644 index 00000000..c661550e --- /dev/null +++ b/lib/philomena_web/config.ex @@ -0,0 +1,12 @@ +defmodule PhilomenaWeb.Config do + @reload_enabled Application.compile_env(:philomena, :vite_reload, false) + @csp_relaxed Application.compile_env(:philomena, :csp_relaxed, false) + + defmacro vite_hmr?(do: do_clause, else: else_clause) do + if(@reload_enabled, do: do_clause, else: else_clause) + end + + defmacro csp_relaxed?(do: do_clause, else: else_clause) do + if(@csp_relaxed, do: do_clause, else: else_clause) + end +end diff --git a/lib/philomena_web/plugs/content_security_policy_plug.ex b/lib/philomena_web/plugs/content_security_policy_plug.ex index d958541e..210ff645 100644 --- a/lib/philomena_web/plugs/content_security_policy_plug.ex +++ b/lib/philomena_web/plugs/content_security_policy_plug.ex @@ -1,4 +1,5 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do + import PhilomenaWeb.Config import Plug.Conn @allowed_sources [ @@ -42,11 +43,15 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do |> Enum.map(&cspify_element/1) |> Enum.join("; ") - if conn.status == 500 and allow_relaxed_csp() do - # Allow Plug.Debugger to function in this case - delete_resp_header(conn, "content-security-policy") + csp_relaxed? do + if conn.status == 500 do + # Allow Plug.Debugger to function in this case + delete_resp_header(conn, "content-security-policy") + else + # Enforce CSP otherwise + put_resp_header(conn, "content-security-policy", csp_value) + end else - # Enforce CSP otherwise put_resp_header(conn, "content-security-policy", csp_value) end end) @@ -64,14 +69,13 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do defp cdn_uri, do: Application.get_env(:philomena, :cdn_host) |> to_uri() defp camo_uri, do: Application.get_env(:philomena, :camo_host) |> to_uri() - defp vite_reload?, do: Application.get_env(:philomena, :vite_reload) - defp default_script_src, do: if(vite_reload?(), do: "'self' localhost:5173", else: "'self'") + defp default_script_src, do: vite_hmr?(do: "'self' localhost:5173", else: "'self'") defp default_connect_src, - do: if(vite_reload?(), do: "'self' localhost:5173 ws://localhost:5173", else: "'self'") + do: vite_hmr?(do: "'self' localhost:5173 ws://localhost:5173", else: "'self'") - defp default_style_src, do: if(vite_reload?(), do: "'self' 'unsafe-inline'", else: "'self'") + defp default_style_src, do: vite_hmr?(do: "'self' 'unsafe-inline'", else: "'self'") defp to_uri(host) when host in [nil, ""], do: "" defp to_uri(host), do: URI.to_string(%URI{scheme: "https", host: host}) @@ -84,6 +88,4 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do Enum.join([key | value], " ") end - - defp allow_relaxed_csp, do: Application.get_env(:philomena, :csp_relaxed, false) end diff --git a/lib/philomena_web/templates/layout/app.html.slime b/lib/philomena_web/templates/layout/app.html.slime index 16a43d7a..e86528eb 100644 --- a/lib/philomena_web/templates/layout/app.html.slime +++ b/lib/philomena_web/templates/layout/app.html.slime @@ -20,7 +20,7 @@ html lang="en" meta name="format-detection" content="telephone=no" = csrf_meta_tag() - = if vite_reload?() do + = vite_hmr? do script type="module" src="http://localhost:5173/@vite/client" script type="module" src="http://localhost:5173/js/app.js" - else diff --git a/lib/philomena_web/views/layout_view.ex b/lib/philomena_web/views/layout_view.ex index 3ea772a7..fe338f09 100644 --- a/lib/philomena_web/views/layout_view.ex +++ b/lib/philomena_web/views/layout_view.ex @@ -1,6 +1,7 @@ defmodule PhilomenaWeb.LayoutView do use PhilomenaWeb, :view + import PhilomenaWeb.Config alias PhilomenaWeb.ImageView alias Philomena.Config alias Plug.Conn