From eb397a6c257424b71d808f103865e6793a9290aa Mon Sep 17 00:00:00 2001 From: hq1 Date: Wed, 28 Jun 2023 12:28:26 +0200 Subject: [PATCH] Dynamically set up session domain (#3089) * Dynamically configure session domain * Fix up error message in runtime config --- config/runtime.exs | 2 +- lib/plausible_web/endpoint.ex | 3 +- .../plugs/runtime_session_adapter.ex | 30 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 lib/plausible_web/plugs/runtime_session_adapter.ex diff --git a/config/runtime.exs b/config/runtime.exs index 22b649029..cfcf85ff4 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -233,7 +233,7 @@ if byte_size(websocket_url) > 0 and Cross-domain websocket authentication is not supported for this server. WEBSOCKET_URL=#{websocket_url} - host must be: '#{base_url.host}', - because BASE_URL=#{base_url} so the host is ``. + because BASE_URL=#{base_url}. """ end diff --git a/lib/plausible_web/endpoint.ex b/lib/plausible_web/endpoint.ex index a0f5411e0..8009ccdc1 100644 --- a/lib/plausible_web/endpoint.ex +++ b/lib/plausible_web/endpoint.ex @@ -9,6 +9,7 @@ defmodule PlausibleWeb.Endpoint do # 5 years, this is super long but the SlidingSessionTimeout will log people out if they don't return for 2 weeks max_age: 60 * 60 * 24 * 365 * 5, extra: "SameSite=Lax" + # domain added dynamically via RuntimeSessionAdapter, see below ] # Serve at "/" the static files from "priv/static" directory. @@ -52,7 +53,7 @@ defmodule PlausibleWeb.Endpoint do plug Plug.MethodOverride plug Plug.Head - plug Plug.Session, @session_options + plug PlausibleWeb.Plugs.RuntimeSessionAdapter, @session_options socket "/live", Phoenix.LiveView.Socket, websocket: [ diff --git a/lib/plausible_web/plugs/runtime_session_adapter.ex b/lib/plausible_web/plugs/runtime_session_adapter.ex new file mode 100644 index 000000000..ae5b1f221 --- /dev/null +++ b/lib/plausible_web/plugs/runtime_session_adapter.ex @@ -0,0 +1,30 @@ +defmodule PlausibleWeb.Plugs.RuntimeSessionAdapter do + @moduledoc """ + A `Plug.Session` adapter that allows configuration at runtime. + Sadly, the plug being wrapped has no MFA option for dynamic + configuration. + + This is currently used so we can dynamically pass the :domain + and have cookies planted across one root domain. + """ + + @behaviour Plug + + @impl true + def init(opts) do + Plug.Session.init(opts) + end + + @impl true + def call(conn, opts) do + Plug.Session.call(conn, patch_cookie_domain(opts)) + end + + defp patch_cookie_domain(%{cookie_opts: cookie_opts} = runtime_opts) do + Map.replace( + runtime_opts, + :cookie_opts, + Keyword.put_new(cookie_opts, :domain, PlausibleWeb.Endpoint.host()) + ) + end +end