Skip to content

Commit e7728dd

Browse files
committed
provide window.LiveDashboard.registerCustomHooks function
1 parent c44ed4d commit e7728dd

File tree

7 files changed

+48
-29
lines changed

7 files changed

+48
-29
lines changed

assets/js/app.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ let Hooks = {
1818
PhxRememberRefresh: PhxRememberRefresh
1919
}
2020

21-
window.customHooks = window.customHooks || {}
22-
2321
let socketPath = document.querySelector("html").getAttribute("phx-socket") || "/live"
2422
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
2523
let liveSocket = new LiveView.LiveSocket(socketPath, Phoenix.Socket, {
26-
hooks: { ...Hooks, ...window.customHooks },
24+
hooks: { ...Hooks, ...window.LiveDashboard.customHooks },
2725
params: (liveViewName) => {
2826
return {
2927
_csrf_token: csrfToken,

dist/js/app.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/app.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/phoenix/live_dashboard/layouts/dash.html.heex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
<!DOCTYPE html>
22
<html lang="en" phx-socket={live_socket_path(@conn)}>
33
<head>
4+
<script nonce={csp_nonce(@conn, :script)}>
5+
window.LiveDashboard = {
6+
customHooks: {},
7+
registerCustomHooks(hooks) {
8+
this.customHooks = {...this.customHooks, ...hooks}
9+
}
10+
}
11+
</script>
412
<%= custom_head_tags(assigns, :after_opening_head_tag) %>
513
<meta charset="utf-8"/>
614
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>

lib/phoenix/live_dashboard/page_builder.ex

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,14 @@ defmodule Phoenix.LiveDashboard.PageBuilder do
125125
126126
defp after_opening_head_tag(assigns) do
127127
~H\"\"\"
128-
<script>
129-
window.customHooks = {
130-
...(window.customHooks || {}),
128+
<script nonce={@csp_nonces[:script]}>
129+
window.LiveDashboard.registerCustomHooks({
131130
MyHook: {
132131
mounted() {
133132
// do something
134133
}
135134
}
136-
}
135+
})
137136
</script>
138137
\"\"\"
139138
end
@@ -156,23 +155,34 @@ defmodule Phoenix.LiveDashboard.PageBuilder do
156155
]
157156
```
158157
159-
The LiveDashboard will merge the `window.customHooks` object into the hooks that are
160-
configured on the LiveSocket.
161-
162-
> #### Warning {: .warning}
163-
>
164-
> If you are building a library that will be used by others, ensure that you are
165-
> not overwriting the `window.customHooks` object instead of extending it.
166-
>
167-
> Instead of `window.customHooks = {...}`,
168-
> use `window.customHooks = {...(window.customHooks || {}), ...}`.
158+
The LiveDashboard provides a function `window.LiveDashboard.registerCustomHooks({ ... })` that you can call
159+
with an object of hook declarations.
169160
170161
Note that in order to use external libraries, you will either need to include them from
171-
a CDN, or bundle them yourself and include them from your apps static paths.
162+
a CDN, or bundle them yourself and include them from your app's static paths.
172163
173-
Also, you are responsible for ensuring that your Content Security Policy (CSP) allows
174-
the hooks to be executed. If you are building a library that will be used by others,
175-
consider including a valid nonce on your script tags.
164+
> #### A note on CSPs and libraries {: .info}
165+
>
166+
> Phoenix LiveDashboard supports CSP nonces for its own assets, configurable using the
167+
> `Phoenix.LiveDashboard.Router.live_dashboard/2` macro by setting the `:csp_nonce_assign_key`
168+
> option. If you are building a library, ensure that you render those CSP nonces on any scripts,
169+
> styles or images of your page. The nonces are passed to your custom page under the `:csp_nonces` assign
170+
> and also available in the `after_opening_head_tag` component.
171+
>
172+
> You should use those when including scripts or styles like this:
173+
>
174+
> ```heex
175+
> <script nonce={@csp_nonces[:script]}>...</script>
176+
> <script nonce={@csp_nonces[:script]} src="..."></script>
177+
> <style nonce={@csp_nonces[:style]}>...</style>
178+
> <link rel="stylesheet" href="..." nonce={@csp_nonces[:style]}>
179+
> ```
180+
>
181+
> This ensures that your custom page can be used when a CSP is in place using the mechanism
182+
> supported by Phoenix LiveDashboard.
183+
>
184+
> If your custom page needs a different CSP policy, for example due to inline styles set by scripts,
185+
> please consider documenting these requirements.
176186
"""
177187

178188
use Phoenix.Component

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ defmodule Phoenix.LiveDashboard.MixProject do
6565
{:stream_data, "~> 0.1", only: :test},
6666
{:ecto_sqlite3, "~> 0.9.1", only: [:dev, :test]},
6767
{:ex_doc, "~> 0.21", only: :docs},
68+
{:makeup_eex, ">= 0.1.1", only: :docs},
6869
{:esbuild, "~> 0.5", only: :dev},
6970
{:dart_sass, "~> 0.7", only: :dev}
7071
]

mix.lock

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
2323
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
2424
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
25-
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
26-
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
25+
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
26+
"makeup_eex": {:hex, :makeup_eex, "1.0.0", "436d4c00204c250b17a775d64e197798aaf374627e6a4f2d3fd3074a8db61db4", [:mix], [{:makeup, "~> 1.2.1 or ~> 1.3", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.1.0 or ~> 1.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "3bb699bc519e4f509f1bf8a2e0ba0e08429edf3580053cd31a4f9c1bc5da86c8"},
27+
"makeup_elixir": {:hex, :makeup_elixir, "1.0.0", "74bb8348c9b3a51d5c589bf5aebb0466a84b33274150e3b6ece1da45584afc82", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49159b7d7d999e836bedaf09dcf35ca18b312230cf901b725a64f3f42e407983"},
2728
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
29+
"makeup_html": {:hex, :makeup_html, "0.1.2", "19d4050c0978a4f1618ffe43054c0049f91fe5feeb9ae8d845b5dc79c6008ae5", [:mix], [{:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b7fb9afedd617d167e6644a0430e49c1279764bfd3153da716d4d2459b0998c5"},
2830
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
2931
"myxql": {:hex, :myxql, "0.6.3", "3d77683a09f1227abb8b73d66b275262235c5cae68182f0cfa5897d72a03700e", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "af9eb517ddaced5c5c28e8749015493757fd4413f2cfccea449c466d405d9f51"},
3032
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},

0 commit comments

Comments
 (0)