Session read/write helpers for multi-account functionality.
Provides functions that work with both Plug.Conn (controllers) and
raw session maps (LiveView hooks) for reading session values, and
Plug.Conn only for writing.
Session Keys
"user"— AshAuthentication subject string, format"<short_name>?id=<UUID>". Both read (on mount/hook) and written (during account switches viaput_user_id/3). Writing to this key is how account switching works at the session level."primary_user_id"— UUID of the primary account owner"session_token"— UUID tying linked accounts to a browser session
Summary
Functions
Clears multi-account session keys ("primary_user_id" and "session_token").
Reads the "primary_user_id" from the session.
Reads the "session_token" from the session.
Parses the user ID from the session "user" key.
Returns true if the session has both "primary_user_id" and "session_token" set.
Sets both "primary_user_id" and "session_token" atomically.
Writes "primary_user_id" to the session.
Writes "session_token" to the session.
Writes the user subject to the session "user" key.
Types
@type conn_or_session() :: Plug.Conn.t() | %{optional(String.t()) => term()}
Functions
@spec clear_multi_account_session(Plug.Conn.t()) :: Plug.Conn.t()
Clears multi-account session keys ("primary_user_id" and "session_token").
Does not clear the "user" key.
Only works with Plug.Conn.
@spec get_primary_user_id(conn_or_session()) :: String.t() | nil
Reads the "primary_user_id" from the session.
Accepts either a Plug.Conn or a raw session map.
@spec get_session_token(conn_or_session()) :: String.t() | nil
Reads the "session_token" from the session.
Accepts either a Plug.Conn or a raw session map.
@spec get_user_id(conn_or_session()) :: String.t() | nil
Parses the user ID from the session "user" key.
The session stores the user subject as "<short_name>?id=<UUID>" (matching
AshAuthentication's subject format). This extracts just the UUID.
Accepts either a Plug.Conn or a raw session map.
Returns the UUID string or nil.
@spec multi_account_session?(conn_or_session()) :: boolean()
Returns true if the session has both "primary_user_id" and "session_token" set.
Accepts either a Plug.Conn or a raw session map.
@spec put_multi_account_session(Plug.Conn.t(), String.t(), String.t()) :: Plug.Conn.t()
Sets both "primary_user_id" and "session_token" atomically.
These two keys must always be set together to establish a valid multi-account session.
@spec put_primary_user_id(Plug.Conn.t(), String.t()) :: Plug.Conn.t()
Writes "primary_user_id" to the session.
@spec put_session_token(Plug.Conn.t(), String.t()) :: Plug.Conn.t()
Writes "session_token" to the session.
@spec put_user_id(Plug.Conn.t(), String.t(), String.t()) :: Plug.Conn.t()
Writes the user subject to the session "user" key.
Constructs the subject string from the given user_id using the format
"<short_name>?id=<UUID>". The short_name parameter defaults to "user",
matching the typical Ash resource short name for User resources. If your
resource uses a different short_name, pass it explicitly.
Only works with Plug.Conn.