PhoenixKit.Utils.Routes (phoenix_kit v1.7.226)

Copy Markdown View Source

Utility functions for working with PhoenixKit routes and URLs.

This module provides helpers for constructing URLs with the correct PhoenixKit prefix configured in the application.

Summary

Functions

Returns a locale-aware admin path. For non-primary locales the locale segment is always emitted. For the primary locale the shape follows the site-wide default_language_no_prefix setting (Languages.default_language_no_prefix?/0): prefixless when the setting is on, prefixed when off.

Whether a path lands on one of the sign-in pages (or /users/log-out).

The bare base URL (scheme + host, no trailing slash), same source url/1 uses.

Returns the default locale (base code) from the Languages module.

Returns true when path is safe to use as a local redirect / return_to target: a binary that begins with a single / but not // or /\ — both of which browsers resolve as protocol-relative, host-switching URLs. Use this to guard user-supplied redirect params against open-redirect attacks.

Returns a locale-aware path using locale from assigns.

Gets the base module name for the parent application.

Resolves where to send a user once they are signed in and confirmed.

Renders ?return_to=<path> for a link, or "" when there is nothing safe to carry. Lets the auth pages hand the pending destination to each other instead of dropping it the moment a visitor switches to another sign-in method.

Returns a full url with preconfigured prefix.

Returns the configured PhoenixKit URL prefix.

Functions

admin_path(url_path, locale)

Returns a locale-aware admin path. For non-primary locales the locale segment is always emitted. For the primary locale the shape follows the site-wide default_language_no_prefix setting (Languages.default_language_no_prefix?/0): prefixless when the setting is on, prefixed when off.

Both URL shapes resolve at the router level — the admin route macros declare /:locale/admin/* AND /admin/* scopes — so either shape is routable. The two shapes share one live_session :phoenix_kit_admin, so locale switching across them stays on the WebSocket (push_navigate) without a full-page reload.

Examples

iex> Routes.admin_path("/admin/users", "uk")
"/phoenix_kit/uk/admin/users"

iex> Routes.admin_path("/admin/users", nil)
"/phoenix_kit/admin/users"

Primary-locale shape depends on the default_language_no_prefix setting (not shown as doctests because the result varies with runtime state):

# setting OFF (default)
Routes.admin_path("/admin/users", "en") #=> "/phoenix_kit/en/admin/users"

# setting ON
Routes.admin_path("/admin/users", "en") #=> "/phoenix_kit/admin/users"

auth_page?(path)

@spec auth_page?(term()) :: boolean()

Whether a path lands on one of the sign-in pages (or /users/log-out).

Public because the after_login_path / after_registration_path changeset applies the same rule when the setting is saved — one list, one predicate, so a new auth route can't be guarded on read and forgotten on write.

Suffix-matched, since the real URL carries the host's mount prefix and an optional locale segment (/app/et/users/log-in). A host page whose own path happens to end in one of these segments is refused too — over-strict rather than allowing a redirect loop.

Examples

iex> PhoenixKit.Utils.Routes.auth_page?("/users/log-in")
true
iex> PhoenixKit.Utils.Routes.auth_page?("/et/users/log-out/")
true
iex> PhoenixKit.Utils.Routes.auth_page?("/dashboard")
false

base_url()

@spec base_url() :: String.t()

The bare base URL (scheme + host, no trailing slash), same source url/1 uses.

For absolutizing a path that is already url-prefixed and locale-prefixed (e.g. a notification's link, built via path/1) — concatenate it onto this directly. Do NOT pass such a path to url/1, which re-applies path/1 and would double-prefix it.

get_default_admin_locale()

Returns the default locale (base code) from the Languages module.

Extracts the base code from the default language (e.g., "en-US" becomes "en"). Falls back to "en" if no default language is configured.

Examples

iex> Routes.get_default_admin_locale()
"en"

local_path?(path)

@spec local_path?(term()) :: boolean()

Returns true when path is safe to use as a local redirect / return_to target: a binary that begins with a single / but not // or /\ — both of which browsers resolve as protocol-relative, host-switching URLs. Use this to guard user-supplied redirect params against open-redirect attacks.

ASCII control characters are rejected too. Browsers strip tab/CR/LF while parsing a URL, so "/\t/evil.example" (from ?return_to=%2F%09%2Fevil.example) becomes //evil.example — a cross-origin navigation — once it reaches window.location. Phoenix.Controller.redirect/2 blocks those itself, but LiveView's validate_local_url! only rejects \\ and a leading //, so a LiveView redirect(socket, to: ...) would otherwise pass it through.

Examples

iex> PhoenixKit.Utils.Routes.local_path?("/admin/dashboard")
true
iex> PhoenixKit.Utils.Routes.local_path?("//evil.com")
false
iex> PhoenixKit.Utils.Routes.local_path?("https://evil.com")
false
iex> PhoenixKit.Utils.Routes.local_path?("/\t/evil.com")
false

locale_aware_path(assigns, url_path)

Returns a locale-aware path using locale from assigns.

This function is specifically designed for use in component templates where the locale needs to be passed explicitly via assigns.

Prefers base locale code for URL generation (current_locale_base), falls back to extracting base from full dialect code (current_locale).

path(url_path, opts \\ [])

phoenix_kit_app_base()

@spec phoenix_kit_app_base() :: String.t()

Gets the base module name for the parent application.

Reads from :phoenix_kit, :layouts_module config (e.g., MprojectWeb.Layouts -> MprojectWeb).

Examples

iex> PhoenixKit.Utils.Routes.phoenix_kit_app_base()
"MprojectWeb"

post_auth_path(candidates \\ [])

@spec post_auth_path([term()]) :: String.t()

Resolves where to send a user once they are signed in and confirmed.

Takes candidate destinations in priority order (e.g. a ?return_to= param, then the session's user_return_to) and returns the first that passes local_path?/1. Falls back to the after_login_path setting, and finally to "/".

The setting is validated as a local path when saved, but is re-guarded here so a hand-edited DB row can't turn a post-auth redirect into an open redirect. Single source of truth for the post-auth landing page — used by the login flow (signed_in_path/1) and by both confirmation LiveViews.

Examples

iex> PhoenixKit.Utils.Routes.post_auth_path(["/checkout"])
"/checkout"
iex> PhoenixKit.Utils.Routes.post_auth_path(["https://evil.com", nil])
"/"
iex> PhoenixKit.Utils.Routes.post_auth_path(["/users/log-out"])
"/"

return_to_query(path)

@spec return_to_query(term()) :: String.t()

Renders ?return_to=<path> for a link, or "" when there is nothing safe to carry. Lets the auth pages hand the pending destination to each other instead of dropping it the moment a visitor switches to another sign-in method.

url(url_path)

Returns a full url with preconfigured prefix.

This function first checks for a configured site URL in Settings, then automatically detects the correct URL from the running Phoenix application endpoint when possible, falling back to static configuration. This ensures that magic links and other email links work correctly in both development and production environments, with full control over the base URL through the Settings admin panel.

url_prefix()

@spec url_prefix() :: String.t()

Returns the configured PhoenixKit URL prefix.

Examples

iex> PhoenixKit.Utils.Routes.url_prefix()
"/phoenix_kit"