Observer.Web.Router (Observer Web v0.2.8)

View Source

Provides mount points for the Web dashboard with customization.

Customizing with a Resolver Callback Module

Implementing a Observer.Web.Resolver callback module allows you to customize the dashboard per-user, i.e. setting access controls.

As a simple example, let's define a module that makes the dashboard read only:

defmodule MyApp.Resolver do
  @behaviour Observer.Web.Resolver

  @impl true
  def resolve_access(_user), do: :read_only
end

Then specify MyApp.Resolver as your resolver:

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", resolver: MyApp.Resolver
end

See the Observer.Web.Resolver docs for more details.

Running Multiple Dashboards

A single router can mount more than one dashboard, each with its own path and :as name:

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", as: :observer_dashboard
  observer_dashboard "/admin/observer", as: :observer_admin_dashboard
end

On Mount Hooks

You can provide a list of hooks to attach to the dashboard's mount lifecycle. Additional hooks are prepended before Observer Web's own Authentication. For example, to run a user-fetching hook and an activation checking hook before mount:

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", on_mount: [MyApp.UserHook, MyApp.ActivatedHook]
end

Customizing the Socket Connection

Applications that use a live socket other than "/live" can override the default socket path in the router. For example, if your live socket is hosted at /observer_live:

socket "/observer_live", Phoenix.LiveView.Socket

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", socket_path: "/observer_live"
end

If your application is hosted in an environment that doesn't support websockets you can use longpolling as an alternate transport. To start, make sure that your live socket is configured for longpolling:

socket "/live", Phoenix.LiveView.Socket,
  longpoll: [connect_info: [session: @session_options], log: false]

Then specify "longpoll" as your transport:

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", transport: "longpoll"
end

Custom Pages

Beyond the built-in pillars, the dashboard can host custom pages implementing the Observer.Web.Page behaviour. Pages are registered with a route name and show up at the end of the navigation bar:

scope "/" do
  pipe_through :browser

  observer_dashboard "/observer", pages: [queue: MyApp.ObserverQueuePage]
end

See the Observer.Web.Page docs for how to build a page.

Content Security Policy

To secure the dashboard, or comply with an existing CSP within your application, you can specify nonce keys for images, scripts and styles.

You'll configure the CSP nonce assign key in your router, where the dashboard is mounted. For example, to use a single nonce for all three asset types:

observer_dashboard("/observer", csp_nonce_assign_key: :my_csp_nonce)

That instructs the dashboard to extract a generated nonce from the assigns map on the plug connection, at the :my_csp_nonce key.

Instead, you can specify different keys for each asset type:

observer_dashboard("/observer",
  csp_nonce_assign_key: %{
    img: :img_csp_nonce,
    style: :style_csp_nonce,
    script: :script_csp_nonce
  }
)

Summary

Functions

Defines read-only JSON API routes over the Observer Web collectors, aimed at automation and AI agents. See Observer.Web.Api for the available endpoints.

Defines an observer dashboard route.

Functions

observer_api(path, opts \\ [])

(macro)

Defines read-only JSON API routes over the Observer Web collectors, aimed at automation and AI agents. See Observer.Web.Api for the available endpoints.

Unlike observer_dashboard/2, no session or LiveView is involved - mount it inside whatever pipeline carries your API authentication:

defmodule MyAppWeb.Router do
  use Phoenix.Router

  import Observer.Web.Router

  pipeline :api_auth do
    plug MyAppWeb.ApiAuth
  end

  scope "/" do
    pipe_through [:api_auth]

    observer_api "/observer/api"
  end
end

Options

observer_dashboard(path, opts \\ [])

(macro)

Defines an observer dashboard route.

It requires a path where to mount the dashboard at and allows options to customize routing.

Options

  • :as — override the route name; otherwise defaults to :observer_dashboard

  • :csp_nonce_assign_key — CSP (Content Security Policy) keys used to authenticate image, style, and script assets by pulling a generated nonce out of the connection's assigns map. May be nil, a single atom, or a map of atoms. Defaults to nil.

  • :logo_path — a custom path for the logo link in the header, allowing the logo to link to another page in your application instead of the Oban dashboard root. Defaults to the jobs page.

  • :on_mount — declares additional module callbacks to be invoked when the dashboard mounts

  • :pages — a keyword list of additional pages, where each key is the route name and each value a module implementing the Observer.Web.Page behaviour, e.g. pages: [queue: MyApp.ObserverQueuePage]. Defaults to [].

  • :resolver — an Observer.Web.Resolver implementation used to customize the dashboard's functionality.

  • :socket_path — a phoenix socket path for live communication, defaults to "/live".

  • :transport — a phoenix socket transport, either "websocket" or "longpoll", defaults to "websocket".

Examples

Mount an observer dashboard at the path "/observer":

defmodule MyAppWeb.Router do
  use Phoenix.Router

  import Observer.Web.Router

  scope "/", MyAppWeb do
    pipe_through [:browser]

    observer_dashboard "/observer"
  end
end

References: