AuroraMeter.LiveDashboard.Auth (Aurora Meter v1.0.0)

View Source

Internal. Not part of the supported API (see API inventory). It may change in any release, including a patch. A host mounts AuroraMeter.LiveDashboard.Page; this is what that page is built from.

The authorization contract both LiveDashboard pages are registered with.

A library page mounted inside Phoenix.LiveDashboard cannot inspect the host's router pipelines, cannot know who is signed in, and must not invent an authorization rule. The two things it can do are done here: refuse to exist until the host makes an explicit statement, and evaluate a host-supplied check on every mount and every refresh.

There is no default and no implicit "allow". validate!/2 accepts three forms and nothing else:

ValueMeaningAllowed on
{module, function, args}called as module.function(socket, args), must return exactly truecore page, Pro page
{:assign, key}requires socket.assigns[key] == truecore page, Pro page
:host_routean explicit statement that the route itself is authenticated and that node-local aggregates may be showncore page only

:host_route is refused by the Pro page with its own message, because the Pro page renders tenant keys, provider references and payment state, and an operator marker is not an acceptable basis for showing another customer's payment state. The core page may accept it because it renders no tenant-identifying value at all: every core section is a node-local aggregate, a checkpoint position or a configuration value. That asymmetry is the substantive control; the marker is the procedural one.

The host wiring both moduledocs show:

# router.ex, inside an already-authenticated scope
live_dashboard "/dashboard",
  metrics: MyApp.Telemetry,
  on_mount: [{MyAppWeb.Admin, :ensure_operator}],
  additional_pages: [
    aurora_meter: {AuroraMeter.LiveDashboard.Page, authorized_by: {:assign, :operator?}}
  ]

What this does not promise

architecture-map.md section 9 says both pages "require the host to mount them inside an authenticated dashboard route". That is a statement about the host, and a library cannot enforce it. What is enforced here is that the host wrote a decision down, and that the decision is re-read on every refresh so a session that loses its marker stops seeing data without waiting for a remount. The residual risk is the host's on_mount hook, and the mitigation that does not depend on the host is that the core page renders no tenant data at all.

Summary

Types

The three accepted forms of the :authorized_by option.

Functions

Whether check allows socket to see data.

A short description of check for the refusal panel.

Returns the :authorized_by value from opts, or raises ArgumentError.

Types

check()

@type check() :: {module(), atom(), term()} | {:assign, atom()} | :host_route

The three accepted forms of the :authorized_by option.

Functions

allowed?(arg1, socket)

@spec allowed?(check(), map()) :: boolean()

Whether check allows socket to see data.

Exactly true allows it. Anything else, including a truthy value that is not true, refuses. A check that raises is treated as a refusal and logged at :warning: a page must not open because somebody's authorization function has a bug in it.

Examples

iex> AuroraMeter.LiveDashboard.Auth.allowed?({:assign, :op?}, %{assigns: %{op?: true}})
true

iex> AuroraMeter.LiveDashboard.Auth.allowed?({:assign, :op?}, %{assigns: %{op?: "yes"}})
false

iex> AuroraMeter.LiveDashboard.Auth.allowed?(:host_route, %{assigns: %{}})
true

describe(arg1)

@spec describe(check()) :: String.t()

A short description of check for the refusal panel.

It names the configured check so an operator seeing the refusal can find the hook that should have set it. It never renders a value the check read.

Examples

iex> AuroraMeter.LiveDashboard.Auth.describe({:assign, :operator?})
"the assign :operator? is not exactly true"

validate!(opts, page)

@spec validate!(
  keyword(),
  :core | :pro
) :: check()

Returns the :authorized_by value from opts, or raises ArgumentError.

page is :core or :pro; the Pro page refuses :host_route.

Examples

iex> AuroraMeter.LiveDashboard.Auth.validate!([authorized_by: :host_route], :core)
:host_route

iex> AuroraMeter.LiveDashboard.Auth.validate!([authorized_by: {:assign, :op?}], :pro)
{:assign, :op?}